Question

I have a hash called count, defined as count = {4=>2, 5=>3, 6=>3, 7=>1}.

I want to take the max value, and then push the key that corresponds to that value into an array, so I do this:

array = []
array.push(count.max_by{|k,v| v}[0])

=>> [5]

However, 6 also has the value 3, which is another maximum value. How do I push this value into the array so I get [5,6] instead of just [5]?

Was it helpful?

Solution

This is the way to choose the max values of the hash:

count.values.max
=> 3

Use the select method on the hash:

count.select{ |k, v| v == count.values.max }
 => {5=>3, 6=>3}

Get the keys:

count.select{ |k, v| v == count.values.max }.keys
 => [5, 6]

And finally assign to an array:

array = count.select{ |k, v| v == count.values.max }.keys

OTHER TIPS

This could probably be improved dramatically, but off the top of my head:

count.group_by{|k,v| v}.max_by{|k,v| k}.last.map(&:first)

First, group the key/value pairs of the hash so that the ones with the same value are in the same groups:

count.group_by{|k,v| v} #=> {2=>[[4, 2]], 3=>[[5, 3], [6, 3]], 1=>[[7, 1]]}

Then get the group with the maximum value:

 .max_by{|k,v| k} #=> [3, [[5, 3], [6, 3]]]

Now, we just want the original keys out of that, so first we take the last element of the pair:

  .last #=> [[5, 3], [6, 3]]

And we want just the first element of each of those nested pairs:

  .map(&:first) #=> [5, 6]

This approach avoids one pass through the map as compared to the select-based solutions. It's probably not a significant performance win unless the data set is really huge, in which case the intermediate data structures being built by my solution will be more of a problem anyway.

max = count.values.max
array = count.keys.select{|k| count[k] == max}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top