在Ruby中查找数组的模式

时间:2014-10-08 05:12:36

标签: ruby

在创建查找数组模式的方法时,我看到人们通过默认值为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}

如果有人可以解释如何找到阵列的模式,我将不胜感激。

2 个答案:

答案 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)的第一个值传递给块并分配给块变量ihash没有密钥1。 (它还没有键。)hash[1] += 1hash[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}