元组数组,当第一个元素相同时,求和值

时间:2018-01-10 02:42:26

标签: arrays ruby

我试图通过第一个元素分组来对数组的元素求和。

ex:
[[1, 8], [3, 16], [1, 0], [1, 1], [1, 1]]

应该给出

[ {1 => 10},  {3 => 16} ]

它是对原始数组中第一个元素为1和3的值进行求和。最终结果中的数据结构并不重要,例如:数组数组,哈希数组或只是哈希数很好。

有些尝试:

k = [[1, 8], [3, 16], [1, 0], [1, 1], [1, 1]]
h = {}
k.inject({}) { |(a,b)| h[a] += b}
#=>    undefined method `+' for nil:NilClass

3 个答案:

答案 0 :(得分:1)

data = [[1, 8], [3, 16], [1, 0], [1, 1], [1, 1]]
data.each_with_object({}) { |(k, v), res| res[k] ||= 0; res[k] += v } 

给出

{1=>10, 3=>16}

还有inject版本,虽然它不是那么简洁:

data.inject({}) { |res, (k, v)| res[k] ||= 0; res[k] += v; res }

inject vs each_with_object

答案 1 :(得分:0)

您非常接近,您的代码需要进行一些更改:

k.inject({}) do |hash, (a, b)|
  if hash[a].nil?
    hash[a] = b
  else
    hash[a] += b
  end

  hash
end

首先,您不需要h变量。 #inject接受一个通常称为累加器的参数,您可以为每个数组元素更改它,然后作为返回值获取。由于您已经将空哈希传递给注入,因此您不需要变量。

接下来,您必须处理散列中尚不存在密钥的情况,即if hash[a].nil?。在这种情况下,我们将b的值分配给密钥为a的哈希值。当密钥存在于哈希中时,我们可以安全地对该值求和。

另一件需要注意的事情是你正在使用块的错误参数。调用#inject时,首先接收累加器(在本例中为散列),然后是迭代元素。

#inject

的文档

答案 2 :(得分:0)

k.group_by(&:first).transform_values {|v| v.map(&:last).sum }

您实际上在问题中使用了“group by”字样,但您从未在代码中对数组进行分组。在这里,我首先按照第一个元素对内部数组进行分组,最后得到:

{ 1 => [[1, 8], [1, 0], [1, 1], [1, 1]], 3 => [[3, 16]] }

接下来,我只想要所有内部数组的最后一个元素,因为我已经知道第一个元素总是成为键,因此我使用Hash#transform_values将两元素数组映射到它们的最后一个元素最后,我Enumerable#sum这些数字。