从数组和频率创建哈希

我有一个数组[1,2,4,5,4,7] ,我想找到每个数字的频率并将其存储在哈希中。 我有这个代码,但它返回NoMethodError: undefined method '+' for nil:NilClass

 def score( array ) hash = {} array.each{|key| hash[key] += 1} end 

期望的输出是

 {1 => 1, 2 => 1, 4 => 2, 5 => 1, 7 => 1 } 

请执行以下操作:

 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} 

或者更多Rubyish使用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} 

为什么NoMethodError: undefined method '+' for nil:NilClass

hash = {}是一个空的has,默认值为nilnilNilclass一个实例, Nilclass没有任何名为#+实例方法。 所以你得到NoMethodError

看看Hash::new文档:

 new → new_hash new(obj) → new_hash 

返回一个新的空哈希。 如果随后通过与散列条目不对应的键访问此散列,则返回的值取决于用于创建散列的新样式。 在第一种forms中,访问返回nil。 如果指定了obj,则此单个对象将用于所有默认值。 如果指定了一个块,则将使用哈希对象和键调用它,并应返回默认值。 如果需要,块负责将值存储在哈希中。

只需使用注入。 这种类型的应用程序正是它的意思。 就像是:

 a.inject(Hash.new(0)) {|hash,word| hash[word] += 1; hash } 

在Ruby 2.4+中:

 def score(array) array.group_by(&:itself).transform_values!(&:size) end 

爱我一些注入 :

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} 

这是一个使用Hash数组初始化程序的简短选项

 Hash[arr.uniq.map {|v| [v, arr.count(v)] }] 

这里的要点是hash[1]在数组中第一次看到1时不存在( nil )。

你需要以某种方式初始化它, hash = Hash.new(0)是最简单的方法。 在这种情况下, 0是您想要的初始值。

或者按方法使用组:

 arr = [1,2,4,5,4,7] Hash[arr.group_by{|x|x}.map{|num,arr| [num, arr.size] }]