2つのリストの要素ごとの追加?


244

私が今持っています:

list1 = [1, 2, 3]
list2 = [4, 5, 6]

欲しい:

[1, 2, 3]
 +  +  +
[4, 5, 6]
|| || ||
[5, 7, 9]

2つのリストを要素ごとに追加するだけです。

確かに2つのリストを繰り返し処理できますが、繰り返したくありません。

そうするための最もPythonicな方法は何ですか?


回答:


364

使用するmapoperator.add

>>> from operator import add
>>> list( map(add, list1, list2) )
[5, 7, 9]

またはzipリスト内包表記:

>>> [sum(x) for x in zip(list1, list2)]
[5, 7, 9]

タイミング比較:

>>> list2 = [4, 5, 6]*10**5
>>> list1 = [1, 2, 3]*10**5
>>> %timeit from operator import add;map(add, list1, list2)
10 loops, best of 3: 44.6 ms per loop
>>> %timeit from itertools import izip; [a + b for a, b in izip(list1, list2)]
10 loops, best of 3: 71 ms per loop
>>> %timeit [a + b for a, b in zip(list1, list2)]
10 loops, best of 3: 112 ms per loop
>>> %timeit from itertools import izip;[sum(x) for x in izip(list1, list2)]
1 loops, best of 3: 139 ms per loop
>>> %timeit [sum(x) for x in zip(list1, list2)]
1 loops, best of 3: 177 ms per loop

10
これらの巨大な配列を使用する場合、@ BasSwinckelsによる派手な解決策はおそらく注目すべきものです。
Henry Gomersall 2013

1
これらのタイミングで使用したPythonのバージョンは何ですか?
arshajii 2013

9
注意-python3では、map()はリストではなく反復可能なものを返します。実際のリストが必要な場合、最初の答えはlist(map(add、list1、
list2

@FLHerneによって指摘されたpython3の問題に注意することは、時間とともにmap重要性を増すだけです。Python 2は3年以内に公式サポートを失います。
nealmcb

1
多くの場合、Python構文が非常にエレガントでシンプルな場合がありますが、残念ながらこれはその1つではありません。そして、そのような単純なタスクの場合、残念です...すでに.extend()メソッドがあるのに、なぜ "+"がリストを連結するのでしょうか?
Nic Sc​​ozzaro、

105

他の人たちは、これを純粋なpythonで行う方法の例を示しました。100.000要素の配列でこれを行う場合は、numpyを使用する必要があります。

In [1]: import numpy as np
In [2]: vector1 = np.array([1, 2, 3])
In [3]: vector2 = np.array([4, 5, 6])

要素ごとの追加を行うことは、

In [4]: sum_vector = vector1 + vector2
In [5]: print sum_vector
[5 7 9]

Matlabと同じように。

Ashwiniの最速バージョンと比較するタイミング:

In [16]: from operator import add
In [17]: n = 10**5
In [18]: vector2 = np.tile([4,5,6], n)
In [19]: vector1 = np.tile([1,2,3], n)
In [20]: list1 = [1,2,3]*n
In [21]: list2 = [4,5,6]*n
In [22]: timeit map(add, list1, list2)
10 loops, best of 3: 26.9 ms per loop

In [23]: timeit vector1 + vector2
1000 loops, best of 3: 1.06 ms per loop

これは25倍速くなります!ただし、状況に合ったものを使用してください。単純なプログラムの場合は、おそらくnumpyをインストールしたくないので、標準のpythonを使用します(そして、私はヘンリーのバージョンが最もPythonicであると思います)。あなたが深刻な数の計算になっている場合numpyは、重労働をやりましょう。スピードがおかしい人のために:numpyソリューションは、周りから始めた方が速いようn = 8です。


59
[a + b for a, b in zip(list1, list2)]

4
@deltab受け入れられた回答はより高速であり、この回答が含まれています(より有益です)
Sibbs Gambling

2
@ perfectionm1ng私はあなたのポイントを理解しています(そして少し気にしないでください)私が提示したソリューションのいずれかを常に使用することを指摘する価値があると思いました(インポートを必要としないので、間違いなく最も簡単です)間違いなくよりpythonic)、または速度が重要な場合Bas Swinckelの答えは、速度が重要な場合に圧倒的に正しいオプションです。
Henry Gomersall 2013

はい。ご意見ありがとうございます。しかし、本質的に[sum(x) for x in zip(list1, list2)]はあなたの答えと同じですよね。:)
Sibbsギャンブル2013

4
@ perfectionm1ng多かれ少なかれ(編集後に私の後に追加されました:)。個人的には、可読性とpythonicnessのために、明示的なタプルのアンパックを伴うa + b表記を好みます。
Henry Gomersall 2013

12

他の人が説明しているように、高速でスペース効率の良いソリューションは、組み込みのベクター操作機能でnumpy(np)を使用することです。

1. Numpyを使用

x = np.array([1,2,3])
y = np.array([2,3,4])
print x+y

2.組み込み

2.1ラムダ

list1=[1, 2, 3]
list2=[4, 5, 6]
print map(lambda x,y:x+y, list1, list2)

map()は複数の引数をサポートしていることに注意してください。

2.2 zipとリストの理解

list1=[1, 2, 3]
list2=[4, 5, 6]
print [x + y for x, y in zip(list1, list2)]

1
ラムダアプローチの場合は+1。このソリューションが他の場所で複製されている他のソリューションと組み合わされているのは残念です。
LondonRob

10

numpy私の意見から使用する方が簡単です:

import numpy as np
list1=[1,2,3]
list2=[4,5,6]
np.add(list1,list2)

結果:

端末の実行

パラメータの詳細については、ここを確認してください:numpy.add


6

おそらく「最もPython的な方法」には、list1とlist2が同じサイズでない場合の処理​​が含まれているはずです。これらの方法のいくつかを適用すると、静かに答えが得られます。numpyアプローチは、おそらくValueErrorで通知します。

例:

import numpy as np
>>> list1 = [ 1, 2 ]
>>> list2 = [ 1, 2, 3]
>>> list3 = [ 1 ]
>>> [a + b for a, b in zip(list1, list2)]
[2, 4]
>>> [a + b for a, b in zip(list1, list3)]
[2]
>>> a = np.array (list1)
>>> b = np.array (list2)
>>> a+b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (2) (3)

これが問題の関数であった場合、どの結果が望ましいでしょうか?


この場合、必ずのzip_longesta fillvalueを使用してitertoolsから調べる必要があり0ます。
Ma0


5

これは2つ以上のリストで機能します。リストのリストを反復処理するが、各リストの要素を処理するためにnumpy加算を使用する

import numpy as np
list1=[1, 2, 3]
list2=[4, 5, 6]

lists = [list1, list2]
list_sum = np.zeros(len(list1))
for i in lists:
   list_sum += i
list_sum = list_sum.tolist()    

[5.0, 7.0, 9.0]

5

おそらくこれはpythonicであり、リストの数が不明で、何もインポートしない場合に少し便利です。

リストが同じ長さである限り、以下の関数を使用できます。

ここで* argsは、可変数のリスト引数を受け入れます(ただし、合計されるのはそれぞれの要素の同じ数のみです)。

返されたリストで*を再び使用して、各リストの要素をアンパックします。

def sum_lists(*args):
    return list(map(sum, zip(*args)))

a = [1,2,3]
b = [1,2,3]  

sum_lists(a,b)

出力:

[2, 4, 6]

または3つのリスト

sum_lists([5,5,5,5,5], [10,10,10,10,10], [4,4,4,4,4])

出力:

[19, 19, 19, 19, 19]

3

ラムダ関数でマップを使用する:

>>> map(lambda x, y: x + y, list1, list2)
[5, 7, 9]

3

私はそれを計時していませんが、これはかなり速いと思います:

import numpy as np
list1=[1, 2, 3]
list2=[4, 5, 6]

list_sum = (np.add(list1, list2)).tolist()

[5, 7, 9]

3

サイズの異なるリストを処理する必要がある場合でも、心配しないでください。素晴らしいitertoolsモジュールがカバーしています:

>>> from itertools import zip_longest
>>> list1 = [1,2,1]
>>> list2 = [2,1,2,3]
>>> [sum(x) for x in zip_longest(list1, list2, fillvalue=0)]
[3, 3, 3, 3]
>>>

Python 2ではzip_longestと呼ばれizip_longestます。

この関連する回答も参照し、別の質問にコメントしてください。


3
[list1[i] + list2[i] for i in range(len(list1))]

1
もっとpythonicでしょう[a + b for (a, b) in zip(list1, list2)]
rayryeng

2

ただし、実際の質問では、リストを反復して結果を生成する必要はありませんが、提案されているすべてのソリューションは、内部的に正確に実行します。

更新するには:すべてのベクトル要素を調べなければ、2つのベクトルを追加できません。したがって、これらのソリューションのほとんどのアルゴリズムの複雑さはBig-O(n)です。ここで、nはベクトルの次元です。

したがって、アルゴリズムの観点から見ると、forループを使用して結果のリストを繰り返し生成することは、論理的でpythonicでもあります。ただし、さらに、このメソッドには追加のライブラリを呼び出したりインポートしたりするオーバーヘッドがありません。

# Assumption: The lists are of equal length.
resultList = [list1[i] + list2[i] for i in range(len(list1))]

ここで示されている/議論されているタイミングは、システムと実装に依存しており、操作の効率を測定するための信頼できる測定にはなりません。いずれの場合でも、ベクトル加算演算の大きなOの複雑さは線形であり、O(n)を意味します。


1
a_list = []
b_list = []
for i in range(1,100):
    a_list.append(random.randint(1,100))

for i in range(1,100):
    a_list.append(random.randint(101,200))
[sum(x) for x in zip(a_list , b_list )]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.