Question

I am really new at ruby. I have created a function to count occurrences of words in a string. However, I am getting NoMethodError for + all the time. I searched, tried different variations, but couldn't solve the problem. Here is the code:

def count_words(str)
    str_down = str.downcase
    arr = str_down.scan(/([\w]+)/).flatten
    hash = Hash[]
    arr.each {|x| hash[x] += 1 }
    (hash.sort_by {|key, value| value}.reverse)
end

Here is the error:

NoMethodError: undefined method `+' for nil:NilClass
    from ./***.rb:14:in `count_words'
    from ./***.rb:14:in `each'
    from ./***.rb:14:in `count_words'
    from (irb):137
Was it helpful?

Solution

Change

hash = Hash[]
arr.each {|x| hash[x] += 1 }

To

hash = {}
arr.each {|x| hash[x] =0 unless hash[x]; hash[x] += 1 }

OR

hash = Hash.new(0)
arr.each {|x| hash[x] += 1 }

EXPLAINATION

hash = {}
hash[1] = "example1" #ASSIGNMENT gives hash = {1: "example1"}
p hash[2] #This gives `nil` by default, as key is not present in hash

To give default value to the key which is not present in hash we have to do the following:

   hash = Hash.new("new value")
   p hash #Gives {}
   p hash[4] #gives "new value"

OTHER TIPS

In the first iteration, h[x] is nil. Trying to add 1 to nil throws error. Setting the initial value of h[x] to 0 will solve the issue.

arr.each {|x| hash[x]||=0; hash[x] += 1 }

instead of

arr.each {|x| hash[x] += 1 }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top