合并多个数组

时间:2018-11-21 09:51:56

标签: ruby sorting

我有一个数组,如下所示。

[
  ["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

但这并不是我想要做的完全,但是我已经接近了。有人有见识吗?

5 个答案:

答案 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'加载类VectorMatrix。参见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) }