在减少数组时使用Hash.new作为初始值

5 ruby hash reduce

我有一个像这样的数组

[1,1,2,3,3,3,4,5,5]
Run Code Online (Sandbox Code Playgroud)

我想计算每个数字的出现次数,我正试图这样做

[1,1,2,3,3,3,4,5,5].reduce(Hash.new(0)) { |hash,number| hash[number] += 1 }
Run Code Online (Sandbox Code Playgroud)

问题是当我尝试运行它时出现以下错误

NoMethodError: undefined method `[]=' for 1:Fixnum
    from (irb):6:in `block in irb_binding'
    from (irb):6:in `each'
    from (irb):6:in `reduce'
    from (irb):6
Run Code Online (Sandbox Code Playgroud)

我可以像这样设置初始值,还是我错了?

tih*_*hom 7

您可以使用each_with_object更清晰的语法

[1,1,2,3,3,3,4,5,5].each_with_object(Hash.new(0)) { |number, hash| hash[number] += 1 }
Run Code Online (Sandbox Code Playgroud)

请注意,参数的顺序是反向的 |number, hash|


Kon*_*che 6

您可以使用reduce,但如果你想的话,你必须再次返回哈希:

[1,1,2,3,3,3,4,5,5].reduce(Hash.new(0)) do |hash,number|
  hash[number] += 1 
  hash
end
Run Code Online (Sandbox Code Playgroud)

没有它,hash[number]将返回值.哈希赋值的值是值本身.该块基于您之前返回的值.

这意味着,在第一次之后它会尝试这样的事情:1[1] += 1这当然不起作用,因为Fixnums没有实现这个方法[]=.


spi*_*ann 5

我喜欢reducehash.update. 它返回数组,我不需要该; hash部分:

[1,1,2,3,3,3,4,5,5].reduce(Hash.new(0)) { |h, n| h.update(n => h[n].next) }
Run Code Online (Sandbox Code Playgroud)