我有一个数组,如下所示。
[
["Horse", 8, 0, 0, 0],
["Horse", 0, 0, 12, 0],
["Horse", 0, 7, 0, 0],
["Dog", 1, 0, 0, 0],
["Dog", 0, 0, 3, 0],
["Dog", 0, 3, 0, 0],
["Test", 5, 0, 0, 0],
["Test", 0, 0, 2, 0],
["Test", 0, 0, 0, 2],
["Cat", 5, 0, 0, 0],
["Cat", 0, 0, 4, 0],
["Cat", 0, 2, 0, 0]
]
我想将以相同的第一个元素开头的不同数组合并在一起,并用另一个数组内部相同位置的值替换0,如下所示。
[
["Horse", 8, 7, 12, 0],
["Dog", 1, 3, 3, 0],
["Test", 5, 0, 2, 2],
["Cat", 5, 2, 4, 0]
]
到目前为止,我具有此功能:
array.each_with_index do |line, idx|
if array[idx+1].present? && line[0] == array[idx+1][0]
line.each_with_index do |l, i|
if l != 0 && array[idx+1][i] == 0
array[idx+1][i] = array[idx][i]
end
end
end
end
但这并不是我想要做的完全,但是我已经接近了。有人有见识吗?
答案 0 :(得分:4)
不确定问题是什么,但是假设给定的数组为arr
,则可以通过以下方式获得结果:
arr
.group_by(&:first)
.map{|k, v| [k, *v.transpose.drop(1).map{|a| a.inject(:+)}]}
或Cary Swoveland指出:
arr
.group_by(&:first)
.map{|k, v| [k, *v.transpose.drop(1).map(&:sum)]}
结果:
[
["Horse", 8, 7, 12, 0],
["Dog", 1, 3, 3, 0],
["Test", 5, 0, 2, 2],
["Cat", 5, 2, 4, 0]
]
答案 1 :(得分:1)
假设您的初始数组存储在arr
中:
arr.each_with_object(Hash.new { |h, k| h[k] = [0] * 4 }) do |(name, *vals), acc|
(0...vals.size).each { |i| acc[name][i] += vals[i] }
end.map { |k, v| [k, *v] }
#⇒ [["Horse", 8, 7, 12, 0],
# ["Dog", 1, 3, 3, 0],
# ["Test", 5, 0, 2, 2],
# ["Cat", 5, 2, 4, 0]]
该解决方案的关键是维护哈希并将其最终转换为数组。哈希通常更易于查找和操作。
累加器使用默认值来简化向其添加新值的过程。
答案 2 :(得分:1)
arr = [["Horse", 8, 0, 0, 0], ["Horse", 0, 0, 12, 0], ["Horse", 0, 7, 0, 0],
["Dog", 1, 0, 0, 0], ["Dog", 0, 0, 3, 0], ["Dog", 0, 3, 0, 0],
["Test", 5, 0, 0, 0], ["Test", 0, 0, 2, 0], ["Test", 0, 0, 0, 2],
["Cat", 5, 0, 0, 0], ["Cat", 0, 0, 4, 0], ["Cat", 0, 2, 0, 0]]
require 'matrix'
arr.each_with_object({}) do |(k,*arr),h|
h[k] = h.key?(k) ? (h[k] + Vector[*arr]) : Vector[*arr]
end.map { |a,v| [a, *v.to_a] }
#=> [["Horse", 8, 7, 12, 0],
# ["Dog", 1, 3, 3, 0],
# ["Test", 5, 0, 2, 2],
# ["Cat", 5, 2, 4, 0]]
需要'matrix'
加载类Vector和Matrix。参见Vector::[],Vector#+和Vector#to_a。
这不需要以任何方式对arr
的元素进行排序。
答案 3 :(得分:0)
有了这个,您将不会受到动物["Dog", 1, 4, 5, 0, 6, 3, ...]
名称的限制
array.group_by { |obj| obj[0] }.map do |key, values|
rest = values.reduce([]) do |memo, value|
value[1..-1].each_with_index do |item, i|
memo[i] ||= 0
memo[i] = [item, memo[i]].max
end
memo
end
[key] + rest
end
答案 4 :(得分:0)
以下是简单的一个
hash = array.group_by(&:first)
hash.map { |k,v| v.map { |x| x[1..-1] }.transpose.map {|x| x.reduce(:+)}.unshift(k) }