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: undefined method '+' for nil:NilClass
def score( array )
hash = {}
array.each{|key| hash[key] += 1}
end
Desired output is
{1 => 1, 2 => 1, 4 => 2, 5 => 1, 7 => 1 }
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}
Do as below :
def score( array )
hash = Hash.new(0)
array.each{|key| hash[key] += 1}
hash
end
score([1,2,4,5,4,7]) # => {1=>1, 2=>1, 4=>2, 5=>1, 7=>1}
Or more Rubyish using Enumerable#each_with_object
:
def score( array )
array.each_with_object(Hash.new(0)){|key,hash| hash[key] += 1}
end
score([1,2,4,5,4,7]) # => {1=>1, 2=>1, 4=>2, 5=>1, 7=>1}
The reason of why
NoMethodError: undefined method '+' for nil:NilClass
?
hash = {}
is an empty has,with default value as nil
.nil
is an instance of Nilclass
,and NilClass
doesn't have any instance method called #+
. So you got NoMethodError
.
Look at the Hash::new
documentation :
new → new_hash
new(obj) → new_hash
Returns a new, empty hash. If this hash is subsequently accessed by a key that doesn’t correspond to a hash entry, the value returned depends on the style of new used to create the hash. In the first form, the access returns nil. If obj is specified, this single object will be used for all default values. If a block is specified, it will be called with the hash object and the key, and should return the default value. It is the block’s responsibility to store the value in the hash if required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With