Penambahan elemen dari 2 daftar?

244

Saya miliki sekarang:

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

Saya ingin memiliki:

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

Cukup dua elemen tambahan daftar.

Saya pasti bisa mengulangi kedua daftar itu, tetapi saya tidak ingin melakukannya.

Apa cara paling Pythonic untuk melakukannya?

Sibbs Gambling
sumber
Kemungkinan duplikat dari vektor ringkas menambahkan dalam Python?
Nikos Alexandris

Jawaban:

364

Gunakan mapdengan operator.add:

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

atau zipdengan pemahaman daftar:

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

Perbandingan waktu:

>>> 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
Ashwini Chaudhary
sumber
10
Jika Anda menggunakan array besar itu, solusi numpy oleh @BasSwinckels mungkin adalah sesuatu yang harus Anda perhatikan.
Henry Gomersall
1
Versi Python apa yang Anda gunakan untuk timing tersebut?
arshajii
9
NB - dalam python3, map () mengembalikan sesuatu yang bisa diulang daripada daftar. Jika Anda memang membutuhkan daftar aktual, jawaban pertama adalah daftar (peta (tambahkan, daftar1, daftar2))
FLHerne
Memperhatikan masalah python3 yang dicatat oleh @FLHerne maphanya akan tumbuh lebih penting dari waktu ke waktu. Python 2 akan kehilangan dukungan resmi dalam waktu kurang dari 3 tahun.
nealmcb
1
Ada banyak waktu di mana sintaksis python benar-benar elegan dan sederhana, tetapi sayangnya ini bukan salah satunya. Dan untuk tugas sederhana seperti itu, sangat disayangkan .... Mengapa mereka membuat "+" menyatukan daftar ketika sudah ada metode .extend ()?
Nic Scozzaro
105

Yang lain memberi contoh bagaimana melakukan ini dengan python murni. Jika Anda ingin melakukan ini dengan array dengan 100.000 elemen, Anda harus menggunakan numpy:

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

Melakukan penambahan elemen-bijaksana sekarang sepele

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

seperti di Matlab.

Waktu untuk membandingkan dengan versi tercepat 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

Jadi ini adalah faktor 25 lebih cepat! Tetapi gunakan apa yang sesuai dengan situasi Anda. Untuk program sederhana, Anda mungkin tidak ingin menginstal numpy, jadi gunakan python standar (dan saya menemukan versi Henry yang paling Pythonic). Jika Anda serius dengan angka-angka yang serius, numpylakukan pengangkatan berat. Untuk speed freaks: sepertinya solusi numpy lebih cepat dimulai n = 8.

Bas Swinckels
sumber
59
[a + b for a, b in zip(list1, list2)]
Henry Gomersall
sumber
4
@deltab Jawaban yang diterima lebih cepat DAN mengandung jawaban ini (lebih informatif)
Sibbs Gambling
2
@ perfectionm1ng meskipun saya mengerti maksud Anda (dan jangan iri sedikit pun) Saya hanya berpikir ada baiknya menunjukkan bahwa saya akan selalu menggunakan salah satu solusi yang saya sajikan (yang mengingat tidak memerlukan impor bisa dibilang paling sederhana, juga sebagai bisa dibilang lebih pythonic), atau di mana kecepatan dihitung, jawaban Bas Swinckel , yang merupakan pilihan tepat di mana kecepatan penting.
Henry Gomersall
Iya. Terima kasih atas pendapatnya. Tetapi pada dasarnya [sum(x) for x in zip(list1, list2)]sama dengan jawaban Anda, bukan? :)
Sibbs Gambling
4
@ perfectionm1ng Lebih atau kurang (meskipun itu ditambahkan setelah saya dengan sunting :). Secara pribadi, saya lebih suka notasi a + b dengan tuple eksplisit membongkar untuk keterbacaan dan pythonicness.
Henry Gomersall
12

Seperti yang dijelaskan oleh orang lain, solusi cepat dan efisien ruang menggunakan numpy (np) dengan kemampuan manipulasi vektor bawaan:

1. Dengan Numpy

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

2. Dengan built-in

2.1 Lambda

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

Perhatikan bahwa map () mendukung banyak argumen.

2.2 pemahaman zip dan daftar

list1=[1, 2, 3]
list2=[4, 5, 6]
print [x + y for x, y in zip(list1, list2)]
MasterControlProgram
sumber
1
+1 untuk pendekatan lambda. Sayang sekali solusi ini dikombinasikan dengan solusi lain yang digandakan di tempat lain.
LondonRob
10

Lebih mudah digunakan numpydari pendapat saya:

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

Hasil:

Eksekusi terminal

Untuk informasi parameter terperinci, periksa di sini: numpy.add

Ludwig Zhou
sumber
6

Mungkin "cara paling pythonic" harus mencakup penanganan case di mana list1 dan list2 tidak berukuran sama. Menerapkan beberapa metode ini akan memberi Anda jawaban dengan tenang. Pendekatan numpy akan memberi tahu Anda, kemungkinan besar dengan ValueError.

Contoh:

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)

Hasil mana yang mungkin Anda inginkan jika ini ada dalam fungsi dalam masalah Anda?

Fred Mitchell
sumber
dalam hal ini salah satu pasti harus melihat ke dalam zip_longestdari itertools dengan fillvaluedari 0.
Ma0
6

Ini sederhana dengan 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])

Lihat dokumen di sini

Jika Anda ingin menerima daftar python:

result.tolist()
Eduardo Basílio
sumber
5

Ini akan berfungsi untuk 2 daftar atau lebih; iterasi melalui daftar daftar, tetapi menggunakan penambahan numpy untuk berurusan dengan elemen dari setiap daftar

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]
kehadiran kecil
sumber
5

Mungkin ini pythonic dan sedikit bermanfaat jika Anda memiliki jumlah daftar yang tidak diketahui, dan tanpa mengimpor apa pun.

Selama daftar memiliki panjang yang sama, Anda dapat menggunakan fungsi di bawah ini.

Di sini * args menerima sejumlah variabel daftar argumen (tetapi hanya menjumlahkan jumlah elemen yang sama di masing-masing).

* Digunakan lagi dalam daftar yang dikembalikan untuk membongkar elemen-elemen dalam setiap daftar.

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

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

sum_lists(a,b)

Keluaran:

[2, 4, 6]

Atau dengan 3 daftar

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

Keluaran:

[19, 19, 19, 19, 19]
Sayap
sumber
3

Gunakan peta dengan fungsi lambda:

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

Saya belum menghitung waktunya tetapi saya menduga ini akan cukup cepat:

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

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

[5, 7, 9]
kehadiran kecil
sumber
3

Jika Anda perlu menangani daftar ukuran yang berbeda, jangan khawatir! Modul itertools yang luar biasa telah Anda liput:

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

Dalam Python 2, zip_longestdisebut izip_longest.

Lihat juga jawaban dan komentar relevan ini untuk pertanyaan lain .

pertama
sumber
3
[list1[i] + list2[i] for i in range(len(list1))]
wgr
sumber
1
Akan lebih banyak pythonic[a + b for (a, b) in zip(list1, list2)]
rayryeng
2

Meskipun, pertanyaan yang sebenarnya tidak ingin beralih pada daftar untuk menghasilkan hasilnya, tetapi semua solusi yang telah diajukan melakukan hal yang tepat di bawah tenda!

Untuk menyegarkan: Anda tidak dapat menambahkan dua vektor tanpa melihat ke semua elemen vektor. Jadi, kompleksitas algoritmik dari sebagian besar solusi ini adalah Big-O (n). Di mana n adalah dimensi vektor.

Jadi, dari sudut pandang algoritmik, menggunakan for for untuk secara iteratif menghasilkan daftar yang dihasilkan juga logis dan pythonic. Namun, selain itu, metode ini tidak memiliki overhead untuk memanggil atau mengimpor pustaka tambahan.

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

Pengaturan waktu yang ditunjukkan / dibahas di sini bergantung pada sistem dan implementasi, dan tidak dapat diukur untuk mengukur efisiensi operasi. Bagaimanapun, kompleksitas O besar dari operasi penambahan vektor adalah linear, artinya O (n).

Ehsan
sumber
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 )]
DSBLR
sumber