我试图通过第一个元素分组来对数组的元素求和。
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
答案 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 }
答案 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
时,首先接收累加器(在本例中为散列),然后是迭代元素。
答案 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
这些数字。