I have an array [1,2,4,5,4,7]
and I want to find the frequency of each number and store it in a hash. I have this code, but it returns NoMethodError: undefine
Ruby 2.7 onwards will have the Enumerable#tally
method that will solve this.
From the trunk documentation:
Tallys the collection. Returns a hash where the keys are the elements and the values are numbers of elements in the collection that correspond to the key.
["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
Just use inject. This type of application is exactly what it is meant for. Something like:
a.inject(Hash.new(0)) {|hash,word| hash[word] += 1; hash }
The point here is that hash[1]
doesn't exist (nil
) when it first sees 1
in the array.
You need to initialize it somehow, and hash = Hash.new(0)
is the easiest way. 0
is the initial value you want in this case.
Here is a short option that uses the Hash array initializer
Hash[arr.uniq.map {|v| [v, arr.count(v)] }]
Or use the group by method:
arr = [1,2,4,5,4,7]
Hash[arr.group_by{|x|x}.map{|num,arr| [num, arr.size] }]
Love me some inject:
results = array.inject(Hash.new(0)) {|hash, arr_element| hash[arr_element] += 1; hash }
1.9.3p448 :082 > array = [1,2,4,5,4,7]
=> [1, 2, 4, 5, 4, 7]
1.9.3p448 :083 > results = array.inject(Hash.new(0)) {|hash, arr_element| hash[arr_element] += 1; hash }
=> {1=>1, 2=>1, 4=>2, 5=>1, 7=>1}