简体   繁体   中英

How to pick top 5 values from a hash?

I have a hash of ids and their scores, it's something like this:

@objects = {1=>57, 4=>12, 3=>9, 5=>3, 55=>47, 32=>39, 17=>27, 29=>97, 39=>58}

How can I pick the top five and drop the rest ?

I'm doing this:

@orderedObject = @objects.sort_by {|k,v| v}.reverse
=>[[29, 97], [39, 58], [1, 57], [55, 47], [32, 39], [17, 27], [4, 12], [3, 9], [5, 3]]

Then I do this: only Keys of the @orderedObjects :

@keys = @orderedObject.map { |key, value| key }

which gives me:

=>[29, 39, 1, 55, 32, 17, 4, 3, 5]

ALL I need is [29, 39, 1, 55, 32] the first 5 indexes. But I'm stuck I don't know how to do this.

You can do

@objects = {1=>57, 4=>12, 3=>9, 5=>3, 55=>47, 32=>39, 17=>27, 29=>97, 39=>58}
@objects.sort_by { |_, v| -v }[0..4].map(&:first)
# => [29, 39, 1, 55, 32]
@objects.sort_by { |_, v| -v }.first(5).map(&:first)
# => [29, 39, 1, 55, 32]

A variant of Prof. Arup's answer:

objects = {1=>57, 4=>12, 3=>9, 5=>3, 55=>47, 32=>39, 17=>27, 29=>97, 39=>58}

objects.sort_by { |k,v| -v }.first(5).to_h.keys #=> [29, 39, 1, 55, 32]

Now suppose 3=>9 were instead 3=>39 and you wanted the keys corresponding to the top 5 values (which, in this case, would be 6 keys, as 39 is the fifth largest value, 3=>39 and 32=>39 ), you could first compute:

threshold = objects.values.sort.last(5).min #=> 39

If you wanted the keys to be ordered by the order of values threshold or larger,

objects.select { |_,v| v >= threshold }.sort_by { |_,v| -v }.map(&:first)
  #=> [29, 39, 1, 55, 3, 32]

If you don't care about the order,

objects.select { |_,v| v >= threshold }.keys #=> [1, 3, 55, 32, 29, 39]

我可以建议这个更详细的要求红宝石> 1.9

Hash[@objects.sort_by{|k,v| -v}.first(5)].keys

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM