How to group by count in array without using loop
Solution 1:
x = arr.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
Solution 2:
Only available under ruby 1.9
Basically the same as Michael's answer, but a slightly shorter way:
x = arr.each_with_object(Hash.new(0)) {|e, h| h[e] += 1}
In similar situations,
- When the starting element is a mutable object such as an
Array
,Hash
,String
, you can useeach_with_object
, as in the case above. -
When the starting element is an immutable object such as
Numeric
, you have to useinject
as below.sum = (1..10).inject(0) {|sum, n| sum + n} # => 55
Solution 3:
There is a short version which is in ruby 2.7 => Enumerable#tally
.
[1,2,1,3,5,2,4].tally #=> { 1=>2, 2=>2, 3=>1, 5=>1, 4=>1 }
# Other possible usage
(1..6).tally { |i| i%3 } #=> { 0=>2, 1=>2, 2=>2 }
Solution 4:
Yet another - similar to others - approach:
result=Hash[arr.group_by{|x|x}.map{|k,v| [k,v.size]}]
- Group by each element's value.
- Map the grouping to an array of [value, counter] pairs.
- Turn the array of paris into key-values within a Hash, i.e. accessible via
result[1]=2 ...
.
Solution 5:
arr.group_by(&:itself).transform_values(&:size)
#=> {1=>2, 2=>2, 3=>1, 5=>1, 4=>1}