ruby:将两个或多个数组的相应成员相加

时间:2010-04-21 11:25:16

标签: ruby arrays sum

我有两个(或更多)数组,每个数组有12个整数(对应于每个月的值)。我想要的就是将它们加在一起,这样我就可以得到一个单独的数组,每个月都有总和值。这是一个有三个值的示例: [1,2,3]和[4,5,6] => [5,7,9]

我能想到的最好的是:

[[1,2,3],[4,5,6]].transpose.map{|arr| arr.inject{|sum, element| sum+element}} #=> [5,7,9]

有更好的方法吗?这似乎是一件基本的事情。

9 个答案:

答案 0 :(得分:47)

以下是Anurag建议的transpose版本:

[[1,2,3], [4,5,6]].transpose.map {|x| x.reduce(:+)}

这适用于任意数量的组件数组。 reduceinject是同义词,但reduce在我看来更清楚地传达了代码的意图......

答案 1 :(得分:8)

为了更清晰的语法(不是最快),您可以使用Vector

require 'matrix'
Vector[1,2,3] + Vector[4,5,6]
=> Vector[5, 7, 9]

对于多个向量,您可以执行以下操作:

arr = [ Vector[1,2,3], Vector[4,5,6], Vector[7,8,9] ]
arr.inject(&:+)
=> Vector[12, 15, 18]

如果您希望将数组加载到Vectors并求和:

arrays = [ [1,2,3], [4,5,6], [7,8,9] ]
arrays.map { |a| Vector[*a] }.inject(:+)
=> Vector[12, 15, 18]

答案 2 :(得分:7)

这是我尝试代码打高尔夫球的事情:

// ruby 1.9 syntax, too bad they didn't add a sum() function afaik
[1,2,3].zip([4,5,6]).map {|a| a.inject(:+)} # [5,7,9]

zip返回[1,4][2,5][3,6],并对每个子数组进行映射求和。

答案 3 :(得分:5)

[[1,2,3],[4,5,6]].transpose.map{|a| a.sum} #=> [5,7,9]

答案 4 :(得分:5)

我谦卑地觉得我看到的其他答案非常复杂,以至于他们会让代码审稿人感到困惑。您需要添加一个解释性注释,这只会增加所需的文本量。

如何改变:

a_arr = [1,2,3]
b_arr = [4,5,6]
(0..2).map{ |i| a_arr[i] + b_arr[i] }

稍微不同的解决方案:(这样你就不会硬编码“2”)

a_arr = [1,2,3]
b_arr = [4,5,6]
c_arr = []
a_arr.each_index { |i| c_arr[i] = a_arr[i] + b_arr[i] }

最后,从数学上讲,这是与此相同的问题:

How do I perform vector addition in Ruby?

答案 5 :(得分:4)

现在我们可以在2.4

中使用sum
nums = [[1, 2, 3], [4, 5, 6]]
nums.transpose.map(&:sum) #=> [5, 7, 9]

答案 6 :(得分:1)

@FriendFX,你对@ user2061694的回答是正确的。它只适用于Rails环境。如果进行以下更改,可以使它以纯Ruby运行...

在IRB

[[0, 0, 0], [2, 2, 1], [1,3,4]].transpose.map {|a| a.inject(:+)}
 => [3, 5, 5]


[[1,2,3],[4,5,6]].transpose.map {|a| a.inject(:+)}
 => [5, 7, 9]

答案 7 :(得分:1)

有关:

zip

您可以reduce然后使用p a.zip(b).map{|v| v.reduce(:+) } #=> [5, 7, 9]

a

或者,如果您确定数组bp a.map.with_index { |v, i| v + b[i] } #=> [5, 7, 9] 的长度始终相同:

static public void ElecOneLine1(System.Data.DataView dv)
    {
        string Path = Commands.LoadFile();
        System.Data.DataTable table = Commands.ReadExcelToTable(Path);
        Commands.ElecDv480V(table);            
        //Commands.OneLineDt(dv);                                  
        Commands.InsertElec1LineBlockscd();
        Commands.DrawOneLineBuscd("OneLineBackground", 35.5478, 23.3750, 0, table.Rows[0]);            
        for (int i = 1; i < 8; i++)
        {
            Commands.DrawOneLineItem("" + table.Rows[1 + i][0], 4 + ((double)i * 3), 12.6835, 0, table.Rows[0], i + 1);                
        }
    }

答案 8 :(得分:0)

这可能不是最佳答案,但可行。

array_one = [1,2,3]
array_two = [4,5,6]
x = 0
array_three = []
while x < array_one.length
  array_three[x] = array_one[x] + array_two[x]
  x += 1
end

=>[5,7,9]

这可能比其他答案更多的代码行,但它仍然是一个答案