Sort an array and store the counters in another array in Ruby

I’m currently sorting an array of arrays (of numbers) in Ruby with this code:

grapes_sorted = vintages_grapes.group_by(&:itself).sort_by do |k, v| -v.size end.map(&:first) 

It works very well. However, I want to store the counters corresponding to each sort in another array.

I tried:

grapes_sorted_counters = []
grapes_sorted = vintages_grapes.group_by(&:itself).sort_by do |k, v| 
                        -v.size 
                        grapes_sorted_counters << v.size 
                    end.map(&:first) 

It store the counters, however, the sort is broken, not ordered like it should be. I suppose v.size (and not -v.size) is the cause of the problem in the block.

How can I store the number of occurrences properly in grapes_sorted_counters[] ? Thanks.

Answer

I believe the problem with your code has been identified, so I will suggest an alternative approach.

grapes = %w|red blue red green yellow red blue blue green red|
  #> ["red", "blue", "red", "green", "yellow", "red", "blue",
  #   "blue", "green", "red"]

grapes.tally.sort_by { |_,count| -count }.map(&:first)
  #=> ["red", "blue", "green", "yellow"]

See Enumerable#tally.

The steps are as follows.

h = grapes.tally
  #=> {"red"=>4, "blue"=>3, "green"=>2, "yellow"=>1} 
a = h.sort_by { |_,count| -count }
  #=> [["red", 4], ["blue", 3], ["green", 2], ["yellow", 1]] 
a.map(&:first)
  #=> ["red", "blue", "green", "yellow"]