在创建查找数组模式的方法时,我看到人们通过默认值为0
的哈希迭代数组:
def mode(array)
hash = Hash.new(0)
array.each do |i|
hash[i]+=1
end
end
或
freq = arr.inject(Hash.new(0)) { |h,v| h[v] += 1; h }
有人可以解释该块的以下部分吗?
hash[i] = hash[i] + 1 or h[v] = h[v] + 1
迭代器如何知道将+1
添加到散列的每个唯一键?例如:
array = [1,1,1,2,3]
freq = arr.inject(Hash.new(0)) { |h,v| h[v] += 1; h }
#=> {1:3, 2:1, 3:1}
如果有人可以解释如何找到阵列的模式,我将不胜感激。
答案 0 :(得分:1)
在第一个示例中,您需要使用该方法返回创建的哈希,或者对哈希进行一些操作以计算模式。我们试试吧,只需返回哈希值(因此我已添加hash
作为最后一行):
def hash_for_mode(array)
hash = Hash.new(0)
array.each do |i|
hash[i]+=1
end
hash
end
array = [1,3,1,4,3]
hash_for_mode(array) #=> {1=>2, 3=>2, 4=>1}
使用hash_for_mode
,您可以轻松计算模式。
通过定义哈希h = Hash.new(0)
,我们告诉Ruby默认值为零。我们的意思是,如果在h[k]
不是k
的关键字时执行的计算取决于h
,则h[k]
将设置为等于默认值。
例如,考虑将array
(我的示例中为1
)的第一个值传递给块并分配给块变量i
。 hash
没有密钥1
。 (它还没有键。)hash[1] += 1
是hash[1] = hash[1] + 1
的简写,因此Ruby将使用默认值零替换等式右侧的hash[1]
,从而生成{{1} }}
当hash[1] => 1
(另一个array
)的第三个值传递到块中时,1
已经存在(并且等于hash[1]
)所以我们只需添加一个给出它是一个新值1
。
万一你想知道,如果我们有:
2
也就是说,仅引用不在散列中的键(此处为hash = Hash.new(0)
hash[1] += 1
hash #=> {1=>1}
puts hash[2] #=> nil
hash #=> {1=>1}
),不会向散列添加键值对。
另一种做同样事情的常见方法是:
puts hash[2]
这取决于:
def hash_for_mode(array)
array.each_with_object({}) { |i,hash| hash[i] = (hash[i] || 0) + 1 }
end
hash_for_mode(array) #=> {1=>2, 3=>2, 4=>1}
(这要求您的哈希不包含任何对(hash[i] || 0) #=> hash[i] if hash already has a key i
(hash[i] || 0) #=> 0 if hash does not have a key i, so hash[k]=>nil
。)
另外,请注意,而不是第一个声明:
k=>nil
和最后一句话:
hash = {}
我使用了Enumerable#each_with_object方法,它返回哈希值。这里首选使用Enumerable#inject(又名hash
)因为您不需要将reduce
返回到迭代器(不需要hash
)。
答案 1 :(得分:0)
array = [1,3,1,4,3]
array.group_by(&:itself).transform_values(&:count)
# => {1=>2, 3=>2, 4=>1}