Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 减少数组时使用Hash.new作为初始值_Ruby_Hash_Reduce - Fatal编程技术网

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

Ruby 减少数组时使用Hash.new作为初始值,ruby,hash,reduce,Ruby,Hash,Reduce,我有一个这样的数组 [1,1,2,3,3,3,4,5,5] 我想计算每个数字出现的次数,我正试着这样做 [1,1,2,3,3,3,4,5,5].reduce(Hash.new(0)) { |hash,number| hash[number] += 1 } 问题是,当我尝试运行它时,出现了以下错误 NoMethodError: undefined method `[]=' for 1:Fixnum from (irb):6:in `block in irb_binding' f

我有一个这样的数组

[1,1,2,3,3,3,4,5,5]
我想计算每个数字出现的次数,我正试着这样做

[1,1,2,3,3,3,4,5,5].reduce(Hash.new(0)) { |hash,number| hash[number] += 1 }
问题是,当我尝试运行它时,出现了以下错误

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

我可以这样设置初始值吗?还是我弄错了?

您可以使用
reduce
,但如果需要,您必须再次返回哈希:

[1,1,2,3,3,3,4,5,5].reduce(Hash.new(0)) do |hash,number|
  hash[number] += 1 
  hash
end
如果没有这个值,
hash[number]
的值将被返回。散列赋值的值就是值本身。该块基于先前返回的值生成

这意味着,在第一次之后,它将尝试以下操作:
1[1]+=1
,这当然不起作用,因为Fixnums没有实现可用于更简洁语法的方法

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

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

我喜欢将
reduce
hash.update一起使用。它返回数组,我不需要
;散列
部分:

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

你的问题已经得到了回答,但这里有另一种剥猫皮的方法:

[编辑以采纳@David的建议。]

a = [1,1,2,3,3,3,4,5,5]
Hash[a.group_by(&:to_i).map {|g| [g.first, g.last.size]}]
这也适用于:

a.group_by{|e| e}.inject({}) {|h, (k,v)| h[k] = v.size; h}
并且可以通过@spickermann使用
update
(或者它的同义词
merge!
)来改进,以摆脱那种恼人的
;h
结尾处:

a.group_by{|e| e}.inject({}) {|h, (k,v)| h.merge!(k => v.size)}
以前,我有:

Hash[*a.group_by(&:to_i).to_a.map {|g| [g.first, g.last.size]}.flatten]
我不喜欢这里。我想使用
来处理
而不是
…按{x | x |}
分组{u>(在上面的一个解决方案中使用),并且正在寻找一种返回接收器或其值的方法
m
to_i
是我能做的最好的方法(例如,
2.to_i=>2
),但只适用于整数。有谁能建议一种方法,将一系列对象的接收器返回到proc,这些对象与
一起使用时,其目的显而易见?

这很简单:

[1,1,2,3,3,3,4,5,5].group_by {|e| e}.collect {|k,v| [k,v.count]}
#=> [[1, 2], [2, 1], [3, 3], [4, 1], [5, 2]]
如果哈希对象中需要结果

Hash[[1,1,2,3,3,3,4,5,5].group_by {|e| e}.collect {|k,v| [k,v.count]}]
#=> {1=>2, 2=>1, 3=>3, 4=>1, 5=>2}

我总是忘记有
每个带有对象的\u
。我发现它比每次迭代都返回散列更干净。很好!我不熟悉
update
。把它藏起来。(读者:请注意,如果不明显的话,他可以使用
+1
而不是
next
)。过于复杂;)您可以将代码简化为Hash[a.group_by(&:to_i).map{g |[g.first,g.last.size]}]
。哈希继承了
可枚举的
映射
,因此无需将其转换为
数组
。此外,您还可以避免展平生成的数组,从而避免使用splat操作符。更不用说,您可以在块参数处拆分通过
map
传递的对象。我同意Ruby缺少返回自身的
.id
方法(被Haskell;)破坏了)