1

通过它们在Ruby中的位置来添加二维数组中的所有元素的最清晰和最有效的方法是什么。例子:

2darray = [[1,2,3],[1,2,3]]
result = [2,4,6]

我有以下代码

def sum_elements_by_position(array)
 total_elements = array.length
 result = []

 for i in 0...array.first.length
   n = 0
   array.each { |subarray| n += subarray[i] }
   result << n
 end
 result
end

假设:所有主要元素的长度相同

对于奖励积分,很高兴看到一个适用于任意长度的主要元素的解决方案

4

3 回答 3

3

您可以zip将第一行与其余行放在一起,然后求和:

def sum_elements_by_position(array)
    array[0].zip(*array[1..-1]).map do |col|
        col.inject(:+)
    end
end
于 2012-12-18T00:30:32.733 回答
0

这是行长度不同时的解决方案。

def sum_cols arr
  arr.reduce( [] ) do |res,row| 
    row.each_with_index { |e,i| res[i] ||= 0; res[i] += e }
    res
  end
end

irb> sum_cols [ [0,1,2], [3,4], [5,6,7,8] ]
=> [8, 11, 9, 8]

@oldergod 建议根据最长的行使用 zip,但找到最长的行并拒绝 nil 是有代价的。我使用上面的示例数组对上述方法进行了以下基准测试,发现 reduce+each_with_index 方法快了 30% 以上:

def sum_cols_using_zip arr
  max_len = arr.map(&:size).max
  ([0] * max_len).zip(*arr).map do |col|
    col.compact.inject(:+)
  end
end
于 2012-12-18T07:31:46.077 回答
0

我会这样做:

a.transpose.map {|x| x.reduce(:+)}

干净、简单、灵活。.transpose转这个

[[1,2,3,4],[2,3,4,5],[3,4,5,6]]

进入这个

[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]

然后.map应用于.reduce每个子数组。.reduce反过来,通过添加子值来聚合子值。或者,更准确地说,通过将+方法应用于它们。

我强烈建议您阅读这些函数的文档,直到您完全理解这个示例,因为它非常简洁地演示了如何以 Ruby 方式思考!

于 2013-01-05T04:43:36.710 回答