web-dev-qa-db-ja.com

ruby:2つ以上の配列の対応するメンバーを合計します

それぞれに12の整数(各月の値に対応)を持つ2つ(またはそれ以上)の配列があります。私が欲しいのは、それらを一緒に追加して、各月の合計値を含む単一の配列を取得することです。これは3つの値の例です:[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]

これを行うより良い方法はありますか?やりたいことはとても基本的なことのようです。

38
jjnevis

Anuragが提案したtransposeバージョンは次のとおりです。

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

これは、任意の数のコンポーネント配列で機能します。 reduceinjectは同義語ですが、reduceは、コードの意図をここでより明確に伝えるように思えます...

50
glenn mcdonald

より明確な構文(最速ではない)を得るには、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]

配列をベクターにロードして合計したい場合:

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

これをコードゴルフしようとする私の試みは次のとおりです:

// 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]を返し、各サブ配列のマップ合計を返します。

7
Anurag

私が目にする他の回答は非常に複雑で、コードレビューアを混乱させると謙虚に感じます。必要なテキストの量を増やすだけの説明コメントを追加する必要があります。

代わりにこれはどうですか:

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] }

最後に、数学的に言えば、これはこれと同じ質問です:

Rubyでベクトル加算を実行するにはどうすればよいですか?

6

これで、2.4で sum を使用できます

nums = [[1, 2, 3], [4, 5, 6]]
nums.transpose.map(&:sum) #=> [5, 7, 9]
5
cavin kwon
[[1,2,3],[4,5,6]].transpose.map{|a| a.sum} #=> [5,7,9]
5
Milap Neupane

ために:

a = [1,2,3]
b = [4,5,6]

Zipしてから、reduceを使用できます。

p a.Zip(b).map{|v| v.reduce(:+) }
#=> [5, 7, 9]

または、配列abが常に同じ長さであると確信している場合:

p a.map.with_index { |v, i| v + b[i] }
#=> [5, 7, 9]
1
Surya

@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]
1
cevaris

これは最善の答えではないかもしれませんが、うまくいきます。

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]

これは他の答えよりもコード行が多いかもしれませんが、それでも答えです

0
Johnson