web-dev-qa-db-ja.com

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

私が今持っています:

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

私は欲しい:

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

2つのリストを単純に要素ごとに追加したものです。

私は確かに2つのリストを繰り返すことができますが、私はそれをしたくありません。

最もPythonicな方法は何ですか?

204
Sibbs Gambling

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
302

他の人たちは純粋な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を使用します(そしてHenryのバージョンが最もPythonicのものだと思います)。あなたが本気で数字を潰しているのであれば、numpyが重い作業をやらせてください。スピードがおかしくなった場合:n = 8から始まる派手な解決策は早いと思われます。

91
Bas Swinckels
[a + b for a, b in Zip(list1, list2)]
51
Henry Gomersall

他の人が説明したように、高速でスペース効率の良い解決策は、組み込みベクトル操作機能を備えた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)]
8
Ralf

私の意見ではnumpyを使うほうが簡単です:

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

結果:

Terminal execution

詳細なパラメータ情報については、こちらをチェックしてください。 numpy.add

6
Ludwig Zhou

おそらく、「最もPythonicな方法」は、list1とlist2が同じサイズではない場合の処理​​を含むべきです。これらの方法のいくつかを適用することは静かにあなたに答えを与えるでしょう。でこぼこしたアプローチは、おそらく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)

これがあなたの問題の関数の中にあったとしたら、どちらの結果がほしいと思いますか?

4
Fred Mitchell

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

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]
3
litepresence

これはnumpy.add()で簡単です

import numpy

list1 = numpy.array([1, 2, 3])
list2 = numpy.array([4, 5, 6])
result = numpy.add(list1, list2) # result receive element-wise addition of list1 and list2
print(result)
array([5, 7, 9])

こちらのドキュメントを参照してください

あなたがpythonリストを受け取りたいなら:

result.tolist()
3

私は時間を計っていないが、これはかなり速いだろうと思う。

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

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

[5, 7, 9]
2
litepresence

おそらくこれは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]
2
Wing

ラムダ関数で地図を使う:

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

あなたが異なるサイズのリストを扱う必要があるならば、心配しないでください!すばらしい 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_longestizip_longest と呼ばれます。

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

1
jjst

しかし、実際の質問は結果を生成するためにリストを反復処理することを望んでいませんが、提案されているすべての解決策はまさにその根底にあるものです。

更新するには:すべてのベクトル要素を調べずに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
Ehsan
[list1[i] + list2[i] for i in range(len(list1))]
1
wgr
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 )]
0
DSBLR