2 개의 목록을 요소별로 추가 하시겠습니까?


244

나는 지금 가지고있어:

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

나는 갖고 싶다 :

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

단순히 두 가지 목록을 요소별로 추가 한 것입니다.

확실히 두 목록을 반복 할 수는 있지만 그렇게하고 싶지 않습니다.

가장 파이썬적인 방법 은 무엇입니까 ?


답변:


364

map함께 사용 operator.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의 numpy 솔루션은 아마도보아야 할 것입니다.
Henry Gomersall

1
이 타이밍에 어떤 Python 버전을 사용 했습니까?
arshajii

9
NB-python3에서 map ()은 목록이 아닌 반복 가능한 것을 반환합니다. 실제 목록이 필요한 경우 첫 번째 답변은 list (map (add, list1, list2))
FLHerne

@FLHerne이 지적한 python3 문제를 지적하면서 map시간이 지남에 따라 더 중요해질 것입니다. Python 2는 3 년 이내에 공식 지원을 잃게됩니다.
nealmcb

1
파이썬 구문이 정말 우아하고 단순 할 때가 여러 번 있지만 불행히도 이것은 그중 하나가 아닙니다. 그리고 그러한 간단한 작업을 위해, 그것은 유감입니다 .... 왜 이미 .extend () 메소드가있을 때 왜 "+"가 목록을 연결합니까?
Nic Scozzaro

105

다른 사람들은 순수한 파이썬에서 이것을 수행하는 방법을 예를 들었습니다. 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를 설치하고 싶지 않을 것이므로 표준 파이썬을 사용하십시오 ( Henry의 버전 이 가장 Pythonic 버전 임을 알았습니다 ). 심각한 수의 크 런칭 numpy이 발생하면 무거운 물건을 들어 올리십시오. 속도 괴물의 경우 : numpy 솔루션이 더 빨리 시작하는 것 같습니다 n = 8.


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

4
@deltab 허용되는 답변이 더 빠르며이 답변에 대한 답변이 포함되어 있습니다 (자세한 정보)
Sibbs Gambling

2
@ perfectionm1ng 비록 당신의 요점을 이해하지만 (1 비트를 원망하지 마십시오) 나는 항상 내가 제시 한 솔루션 중 하나를 사용할 것이라고 지적 할 가치가 있다고 생각했습니다 (수입이 필요하지 않은 경우 가장 간단합니다) Bas Swinckel 의 대답은 속도가 중요 할 때 압도적으로 올바른 옵션입니다.
Henry Gomersall

예. 의견 감사합니다. 그러나 본질적 [sum(x) for x in zip(list1, list2)]으로 당신의 대답과 동일합니까? :)
Sibbs Gambling

4
@ perfectionm1ng 더 많거나 적습니다 (하지만 편집 후에 추가했습니다 :). 개인적으로, 나는 가독성과 pythonicness를 위해 명시적인 튜플 압축 풀기가있는 a + b 표기법을 선호합니다.
Henry Gomersall

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 우편 및 목록 이해

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

아마도 "가장 파이썬적인 방법"은 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를 itertools에서 fillvalue0.
Ma0

6

이것은 간단합니다 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])

여기 doc 참조

파이썬 목록을 수신하려면 다음을 수행하십시오.

result.tolist()

5

이것은 두 개 이상의 목록에서 작동합니다. 목록 목록을 반복하지만 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]
>>>

파이썬 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 20:50에

2

실제 질문은 결과를 생성하기 위해 목록을 반복하고 싶지 않지만 제안 된 모든 솔루션은 정확히 후드 아래에 있습니다.

새로 고치려면 : 모든 벡터 요소를 보지 않고 두 개의 벡터를 추가 할 수 없습니다. 따라서 이러한 솔루션 대부분의 알고리즘 복잡도는 Big-O (n)입니다. 여기서 n은 벡터의 치수입니다.

따라서 알고리즘 관점에서 for 루프를 사용하여 결과 목록을 반복적으로 생성하는 것은 논리적이고 비판적입니다. 그러나이 방법에는 추가 라이브러리를 호출하거나 가져 오는 오버 헤드가 없습니다.

# 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.