İki listenin element olarak eklenmesi?


Yanıtlar:


364

Kullanım mapile operator.add:

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

veya zipbir liste kavrayışı ile:

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

Zamanlama karşılaştırmaları:

>>> 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
Bu büyük dizileri kullanırsanız, @BasSwinckels'in sayısal çözümü muhtemelen bakmanız gereken bir şeydir.
Henry Gomersall

1
Bu zamanlamalar için hangi Python sürümünü kullandınız?
arshajii

9
Not - python3'te, map () bir liste yerine yinelenebilir bir şey döndürür. Gerçek bir listeye ihtiyacınız varsa, ilk cevap listedir (harita (ekle,
liste1, liste2

@FLHerne tarafından not edilen python3 sorununun mapzaman içinde daha da önem kazanacağına dikkat çekmek . Python 2, 3 yıldan az bir sürede resmi desteğini kaybedecek.
nealmcb

1
Python sözdiziminin gerçekten zarif ve basit olduğu birçok kez var, ancak maalesef bu onlardan biri değil. Ve bu kadar basit bir görev için üzücü .... Neden .extend () yöntemi varken listeleri "+" birleştirmeliyiz?
Nic Scozzaro

105

Diğerleri bunun nasıl saf python'da yapılacağına dair örnekler verdi. Bunu 100.000 element içeren dizilerle yapmak istiyorsanız numpy kullanmalısınız:

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

Öğe bazında ekleme yapmak artık önemsiz

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

Tıpkı Matlab'daki gibi.

Ashwini'nin en hızlı versiyonu ile karşılaştırma zamanı:

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

Yani bu daha hızlı bir faktör 25! Ama durumunuza uygun olanı kullanın. Basit bir program için, muhtemelen numpy yüklemek istemezsiniz, bu yüzden standart python kullanın (ve Henry'nin sürümünü en Pythonic olanı buluyorum ). Eğer ciddi sayıda gıcırdama yaşıyorsanız numpy, ağır kaldırma yapalım . Hız düşkünleri için: görünüşe göre numpy çözümü daha hızlı başlıyor n = 8.


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

4
@deltab Kabul edilen cevap daha hızlı VE bu cevabı içeriyor (daha bilgilendirici)
Sibbs Gamball

2
@ perfectionm1ng gerçi ben anlıyorum (ve bir bit yalvarmıyorum) Ben sadece her zaman sunduğum çözümü kullanacağımı işaret etmeye değer olduğunu düşündüm (ki hiçbir ithalat gerektirmediği takdirde tartışmasız en basit olanı da tartışmasız olarak daha pitonik olarak) ya da hızın önemli olduğu yerlerde, hızın önemli olduğu büyük ölçüde doğru seçenek olan Bas Swinckel'in cevabı .
Henry Gomersall

Evet. Görüş için teşekkürler. Ama aslında [sum(x) for x in zip(list1, list2)]cevabınızla aynı, değil mi? :)
Sibbs Kumar

4
@ perfectionm1ng Az çok (benimkilerden sonra bir düzenleme ile eklenmiş olsa da :). Şahsen, okunabilirlik ve pythonicness için açık tuple açma ile a + b gösterimini tercih ederim.
Henry Gomersall

12

Başkaları tarafından tarif edildiği gibi, hızlı ve aynı zamanda yerden tasarruf sağlayan bir çözüm, dahili vektör manipülasyon kabiliyeti ile numpy (np) kullanıyor:

1. Numpy ile

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

2. yerleşik

2.1 Lambda

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

Map () işlevinin birden çok bağımsız değişkeni desteklediğine dikkat edin.

2.2 zip ve liste anlama

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

1
Lambda yaklaşımı için +1. Bu çözümün başka yerlerde çoğaltılan diğer çözümlerle birleştirilmesi utanç vericidir.
LondonRob

10

Bence kullanmak daha basit numpy:

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

Sonuçlar:

Terminal yürütme

Ayrıntılı parametre bilgileri için buraya bakın: numpy.add


6

Belki de "en pitonik yol" list1 ve list2'nin aynı boyutta olmadığı durumun ele alınmasını içermelidir. Bu yöntemlerden bazılarını uygulamak size sessizce bir cevap verecektir. Numpy yaklaşımı, büyük olasılıkla bir ValueError ile bunu size bildirir.

Misal:

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)

Sorununuzda bir işlev içindeyse hangi sonucu isteyebilirsiniz?


bu durumda kesinlikle içine bakmak gerekir zip_longestbir ile itertools gelen fillvaluebir 0.
Ma0

6

Bu basit 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])

Burada dokümanı görün

Bir python listesi almak istiyorsanız:

result.tolist()

5

Bu, 2 veya daha fazla liste için çalışır; liste listesinde yineleme yapmak, ancak her listenin öğeleriyle başa çıkmak için numpy ilavesini kullanmak

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

Belki de bilinmeyen sayıda listeniz varsa ve hiçbir şey içe aktarmadan pitoniktir ve biraz kullanışlıdır.

Listeler aynı uzunlukta olduğu sürece, aşağıdaki işlevi kullanabilirsiniz.

Burada * args değişken sayıda liste bağımsız değişkenini kabul eder (ancak her birinde yalnızca aynı sayıda öğe toplar).

*, Listelerin her birindeki öğeleri açmak için döndürülen listede tekrar kullanılır.

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

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

sum_lists(a,b)

Çıktı:

[2, 4, 6]

Veya 3 listeyle

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

Çıktı:

[19, 19, 19, 19, 19]

3

Lambda fonksiyonlu harita kullanın:

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

3

Zamanlamadım ama bunun oldukça hızlı olacağını düşünüyorum:

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

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

[5, 7, 9]


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

1
Daha [a + b for (a, b) in zip(list1, list2)]
pitonik

2

Her ne kadar, asıl soru sonucu üretmek için liste üzerinde tekrar etmek istemiyor, ancak önerilen tüm çözümler tam olarak kaputun altında!

Yenilemek için: Tüm vektör öğelerine bakmadan iki vektör ekleyemezsiniz. Dolayısıyla, bu çözümlerin çoğunun algoritmik karmaşıklığı Big-O (n) 'dir. Burada n, vektörün boyutudur.

Yani, algoritmik bir bakış açısından, sonuçta oluşan listeyi yinelemeli olarak oluşturmak için bir for döngüsü kullanmak da mantıklı ve pitoniktir. Ancak, ek olarak, bu yöntem herhangi bir ek kitaplığı çağırmak veya almak için ek yüke sahip değildir.

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

Burada gösterilen / tartışılan zamanlamalar sistem ve uygulamaya bağlıdır ve operasyonun verimliliğini ölçmek için güvenilir bir önlem olamaz. Her durumda, vektör ekleme işleminin büyük O karmaşıklığı doğrusaldır, yani 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 )]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.