Reputation: 6937
In a Ruby script,
Given:
hash = {
'This is the first sentence.' => 5,
'This is the second sentence.' => 1,
'This is the last sentence.' => 6
}
Then:
choose_best(hash, 2)
Should return:
['This is the first sentence.', 'This is the last sentence.']
All the methods I can think of involve reordering the hash, thus losing the order of the sentences. What would be the best way to tackle this?
Upvotes: 2
Views: 1302
Reputation: 87386
Starting in Ruby 2.2.0, Enumerable#max_by
takes an optional integer argument that makes it return an array instead of just a single element. Therefore, we can do:
hash = {
'This is the first sentence.' => 6,
'This is the second sentence.' => 1,
'This is the last sentence.' => 5
}
p hash.max_by(2, &:last).map(&:first).sort_by { |k| hash.keys.index k }
# => ["This is the first sentence.", "This is the last sentence."]
The call to sort_by
at the end guarantees the sentences are in the right order, as you requested.
Upvotes: 0
Reputation: 168091
def extract hash, n
min = hash.values.sort[-n]
a = []
i = 0
hash.each{|k, v| (a.push(k) and i += 1) if i < n and v >= min}
a
end
Upvotes: 2
Reputation: 80065
hash = {
'This is the first sentence.' => 5,
'This is the second sentence.' => 1,
'This is the last sentence.' => 6
}
cutoff_val = hash.values.sort[-2] #cf. sawa
p hash.select{|k,v| v >= cutoff_val }
# =>{"This is the first sentence."=>5, "This is the last sentence."=>6}
Upvotes: 1
Reputation: 95298
Try the following monster:
hash.map(&:reverse).each_with_index
.sort_by(&:first).reverse
.take(2)
.sort_by(&:last)
.map { |(_,s),_| s }
Another functional one:
hash.to_a.values_at(*hash.values.each_with_index
.sort.reverse
.map(&:last)
.sort.take(2))
.map(&:first)
Note however, that as an unordered data structure, a hash table is not really suitable for this use case (although the order is remembered in Ruby 1.9). You should use an array instead (the sorting code remains the same):
sentences = [
['This is the first sentence.', 5],
['This is the second sentence.', 1],
['This is the last sentence.', 6],
]
Upvotes: 2
Reputation: 2059
a = hash.sort_by { |sentence, score| score }.reverse
The array a now contains pairs of values of your top scoring sentences. You can select the first N of them.
hash = {"foo" => 7, "bar" => 2, "blah" => 3 }
a = hash.sort_by { |sentence, score| score }.reverse
=> [["foo", 7], ["blah", 3], ["bar", 2]]
Upvotes: -1