Element-wise addition of 2 lists?
Question:
I have now:
list1 = [1, 2, 3]
list2 = [4, 5, 6]
I wish to have:
[1, 2, 3]
+ + +
[4, 5, 6]
|| || ||
[5, 7, 9]
Simply an element-wise addition of two lists.
I can surely iterate the two lists, but I don’t want do that.
What is the most Pythonic way of doing so?
Answers:
Use map
with operator.add
:
>>> from operator import add
>>> list( map(add, list1, list2) )
[5, 7, 9]
or zip
with a list comprehension:
>>> [sum(x) for x in zip(list1, list2)]
[5, 7, 9]
Timing comparisons:
>>> 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
[a + b for a, b in zip(list1, list2)]
The others gave examples how to do this in pure python. If you want to do this with arrays with 100.000 elements, you should use numpy:
In [1]: import numpy as np
In [2]: vector1 = np.array([1, 2, 3])
In [3]: vector2 = np.array([4, 5, 6])
Doing the element-wise addition is now as trivial as
In [4]: sum_vector = vector1 + vector2
In [5]: print sum_vector
[5 7 9]
just like in Matlab.
Timing to compare with Ashwini’s fastest version:
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
So this is a factor 25 faster! But use what suits your situation. For a simple program, you probably don’t want to install numpy, so use standard python (and I find Henry’s version the most Pythonic one). If you are into serious number crunching, let numpy
do the heavy lifting. For the speed freaks: it seems that the numpy solution is faster starting around n = 8
.
Perhaps “the most pythonic way” should include handling the case where list1 and list2 are not the same size. Applying some of these methods will quietly give you an answer. The numpy approach will let you know, most likely with a ValueError.
Example:
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)
Which result might you want if this were in a function in your problem?
Use map with lambda function:
>>> map(lambda x, y: x + y, list1, list2)
[5, 7, 9]
I haven’t timed it but I suspect this would be pretty quick:
import numpy as np
list1=[1, 2, 3]
list2=[4, 5, 6]
list_sum = (np.add(list1, list2)).tolist()
[5, 7, 9]
This will work for 2 or more lists; iterating through the list of lists, but using numpy addition to deal with elements of each list
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]
[list1[i] + list2[i] for i in range(len(list1))]
If you need to handle lists of different sizes, worry not! The wonderful itertools module has you covered:
>>> 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]
>>>
In Python 2, zip_longest
is called izip_longest
.
See also this relevant answer and comment on another question.
As described by others, a fast and also space efficient solution is using numpy (np) with it’s built-in vector manipulation capability:
1. With Numpy
x = np.array([1,2,3])
y = np.array([2,3,4])
print x+y
2. With built-ins
2.1 Lambda
list1=[1, 2, 3]
list2=[4, 5, 6]
print map(lambda x,y:x+y, list1, list2)
Notice that map() supports multiple arguments.
2.2 zip and list comprehension
list1=[1, 2, 3]
list2=[4, 5, 6]
print [x + y for x, y in zip(list1, list2)]
Although, the actual question does not want to iterate over the list to generate the result, but all the solutions that has been proposed does exactly that under-neath the hood!
To refresh: You cannot add two vectors without looking into all the vector elements. So, the algorithmic complexity of most of these solutions are Big-O(n). Where n is the dimension of the vector.
So, from an algorithmic point of view, using a for loop to iteratively generate the resulting list is logical and pythonic too. However, in addition, this method does not have the overhead of calling or importing any additional library.
# Assumption: The lists are of equal length.
resultList = [list1[i] + list2[i] for i in range(len(list1))]
The timings that are being showed/discussed here are system and implementation dependent, and cannot be reliable measure to measure the efficiency of the operation. In any case, the big O complexity of the vector addition operation is linear, meaning O(n).
It’s simpler to use numpy
from my opinion:
import numpy as np
list1=[1,2,3]
list2=[4,5,6]
np.add(list1,list2)
Results:
For detailed parameter information, check here: numpy.add
This is simple with 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])
If you want to receiver a python list:
result.tolist()
Perhaps this is pythonic and slightly useful if you have an unknown number of lists, and without importing anything.
As long as the lists are of the same length, you can use the below function.
Here the *args accepts a variable number of list arguments (but only sums the same number of elements in each).
The * is used again in the returned list to unpack the elements in each of the lists.
def sum_lists(*args):
return list(map(sum, zip(*args)))
a = [1,2,3]
b = [1,2,3]
sum_lists(a,b)
Output:
[2, 4, 6]
Or with 3 lists
sum_lists([5,5,5,5,5], [10,10,10,10,10], [4,4,4,4,4])
Output:
[19, 19, 19, 19, 19]
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 )]
- The zip function is useful here, used with a list comprehension
v1
, v2
.
- If you have a list of lists (instead of just two lists) you can use
v3
.
- For lists with different length (for example: By adding 1 to the end of the first/secound list), then you can try something like this (using zip_longest) –
v4
first = [1, 2, 3, 1]
second = [4, 5, 6]
output: [5, 7, 9, 1]
-
If you have an unknown number of lists of the same length, you can use the function v5
.
-
v6
– The operator module exports a set of efficient functions corresponding to the intrinsic operators of Python. For example, operator.add(x, y)
is equivalent to the expression x+y
.
-
v7
– Assuming both lists first
and second
have same length, you do not need zip or anything else.
################
first = [1, 2, 3]
second = [4, 5, 6]
####### v1 ########
third1 = [sum(i) for i in zip(first,second)]
####### v2 ########
third2 = [x + y for x, y in zip(first, second)]
####### v3 ########
lists_of_lists = [[1, 2, 3], [4, 5, 6]]
third3 = [sum(x) for x in zip(*lists_of_lists)]
####### v4 ########
from itertools import zip_longest
third4 = list(map(sum, zip_longest(first, second, fillvalue=0)))
####### v5 ########
def sum_lists(*args):
return list(map(sum, zip(*args)))
third5 = sum_lists(first, second)
####### v6 ########
import operator
third6 = list(map(operator.add, first,second))
####### v7 ########
third7 =[first[i]+second[i] for i in range(len(first))]
####### v(i) ########
print(third1) # [5, 7, 9]
print(third2) # [5, 7, 9]
print(third3) # [5, 7, 9]
print(third4) # [5, 7, 9]
print(third5) # [5, 7, 9]
print(third6) # [5, 7, 9]
print(third7) # [5, 7, 9]
Several methods are
- Using Numpy
import numpy as np
x = np.array([2,3,3])
y = np.array([1,2,6])
print(type(x)) # <class 'numpy.ndarray'>
print(type(y)) # <class 'numpy.ndarray'>
print(x+y) # [3 5 9]
print(type(x+y)) # <class 'numpy.ndarray'>
In the above code, You can see input and output are NumPy array formats.
import numpy as np
list1=[4,2,2,5]
list2=[2,1,6,7]
print(type(list1)) # <class 'list'>
print(type(list2)) # <class 'list'>
print(np.add(list1,list2)) # [ 6 3 8 12]
print(type(np.add(list1,list2))) # <class 'numpy.ndarray'>
Here, Input and output are in different formats.
- Using Numpy add
import numpy as np
list1=[3, 1, 4]
list2=[0, 9, 7]
print(type(list1)) # <class 'list'>
print(type(list2)) # <class 'list'>
print(np.add(list1, list2).tolist()) # [3, 10, 11]
print(type(np.add(list1, list2).tolist())) # <class 'list'>
In this example, explicitly we are converting NumPy array to list type using to_list()
list1=[1, 3, 3]
list2=[3, 6, 8]
print(map(lambda x,y:x+y, list1, list2)) # <map object at 0x7fea235260a0>
print(list(map(lambda x,y:x+y, list1, list2))) # [4, 9, 11]
- Using zip and list comprehension
list1=[3, 1, 3]
list2=[1, 1, 3]
print(type(list1)) # <class 'list'>
print(type(list2)) # <class 'list'>
print(x + y for x, y in zip(list1, list2)) # <generator object <genexpr> at 0x7f755307b6d0>
print(list(x + y for x, y in zip(list1, list2))) # [4, 2, 6]
print(type([x + y for x, y in zip(list1, list2)])) # <class 'list'>
print(sum(x) for x in zip(list1, list2)) # <generator object <genexpr> at 0x7f4c623e76d0>
print(list(sum(x) for x in zip(list1, list2))) # [4, 2, 6]
print(type([sum(x) for x in zip(list1, list2)])) # <class 'list'>
- Using Map and operator.add
from operator import add
list1=[3, 1, 3]
list2=[1, 1, 3]
print(list(map(add, list1, list2))) # [4, 2, 6]
I have now:
list1 = [1, 2, 3]
list2 = [4, 5, 6]
I wish to have:
[1, 2, 3]
+ + +
[4, 5, 6]
|| || ||
[5, 7, 9]
Simply an element-wise addition of two lists.
I can surely iterate the two lists, but I don’t want do that.
What is the most Pythonic way of doing so?
Use map
with operator.add
:
>>> from operator import add
>>> list( map(add, list1, list2) )
[5, 7, 9]
or zip
with a list comprehension:
>>> [sum(x) for x in zip(list1, list2)]
[5, 7, 9]
Timing comparisons:
>>> 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
[a + b for a, b in zip(list1, list2)]
The others gave examples how to do this in pure python. If you want to do this with arrays with 100.000 elements, you should use numpy:
In [1]: import numpy as np
In [2]: vector1 = np.array([1, 2, 3])
In [3]: vector2 = np.array([4, 5, 6])
Doing the element-wise addition is now as trivial as
In [4]: sum_vector = vector1 + vector2
In [5]: print sum_vector
[5 7 9]
just like in Matlab.
Timing to compare with Ashwini’s fastest version:
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
So this is a factor 25 faster! But use what suits your situation. For a simple program, you probably don’t want to install numpy, so use standard python (and I find Henry’s version the most Pythonic one). If you are into serious number crunching, let numpy
do the heavy lifting. For the speed freaks: it seems that the numpy solution is faster starting around n = 8
.
Perhaps “the most pythonic way” should include handling the case where list1 and list2 are not the same size. Applying some of these methods will quietly give you an answer. The numpy approach will let you know, most likely with a ValueError.
Example:
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)
Which result might you want if this were in a function in your problem?
Use map with lambda function:
>>> map(lambda x, y: x + y, list1, list2)
[5, 7, 9]
I haven’t timed it but I suspect this would be pretty quick:
import numpy as np
list1=[1, 2, 3]
list2=[4, 5, 6]
list_sum = (np.add(list1, list2)).tolist()
[5, 7, 9]
This will work for 2 or more lists; iterating through the list of lists, but using numpy addition to deal with elements of each list
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]
[list1[i] + list2[i] for i in range(len(list1))]
If you need to handle lists of different sizes, worry not! The wonderful itertools module has you covered:
>>> 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]
>>>
In Python 2, zip_longest
is called izip_longest
.
See also this relevant answer and comment on another question.
As described by others, a fast and also space efficient solution is using numpy (np) with it’s built-in vector manipulation capability:
1. With Numpy
x = np.array([1,2,3])
y = np.array([2,3,4])
print x+y
2. With built-ins
2.1 Lambda
list1=[1, 2, 3]
list2=[4, 5, 6]
print map(lambda x,y:x+y, list1, list2)
Notice that map() supports multiple arguments.
2.2 zip and list comprehension
list1=[1, 2, 3]
list2=[4, 5, 6]
print [x + y for x, y in zip(list1, list2)]
Although, the actual question does not want to iterate over the list to generate the result, but all the solutions that has been proposed does exactly that under-neath the hood!
To refresh: You cannot add two vectors without looking into all the vector elements. So, the algorithmic complexity of most of these solutions are Big-O(n). Where n is the dimension of the vector.
So, from an algorithmic point of view, using a for loop to iteratively generate the resulting list is logical and pythonic too. However, in addition, this method does not have the overhead of calling or importing any additional library.
# Assumption: The lists are of equal length.
resultList = [list1[i] + list2[i] for i in range(len(list1))]
The timings that are being showed/discussed here are system and implementation dependent, and cannot be reliable measure to measure the efficiency of the operation. In any case, the big O complexity of the vector addition operation is linear, meaning O(n).
It’s simpler to use numpy
from my opinion:
import numpy as np
list1=[1,2,3]
list2=[4,5,6]
np.add(list1,list2)
Results:
For detailed parameter information, check here: numpy.add
This is simple with 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])
If you want to receiver a python list:
result.tolist()
Perhaps this is pythonic and slightly useful if you have an unknown number of lists, and without importing anything.
As long as the lists are of the same length, you can use the below function.
Here the *args accepts a variable number of list arguments (but only sums the same number of elements in each).
The * is used again in the returned list to unpack the elements in each of the lists.
def sum_lists(*args):
return list(map(sum, zip(*args)))
a = [1,2,3]
b = [1,2,3]
sum_lists(a,b)
Output:
[2, 4, 6]
Or with 3 lists
sum_lists([5,5,5,5,5], [10,10,10,10,10], [4,4,4,4,4])
Output:
[19, 19, 19, 19, 19]
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 )]
- The zip function is useful here, used with a list comprehension
v1
,v2
. - If you have a list of lists (instead of just two lists) you can use
v3
. - For lists with different length (for example: By adding 1 to the end of the first/secound list), then you can try something like this (using zip_longest) –
v4
first = [1, 2, 3, 1]
second = [4, 5, 6]
output: [5, 7, 9, 1]
-
If you have an unknown number of lists of the same length, you can use the function
v5
. -
v6
– The operator module exports a set of efficient functions corresponding to the intrinsic operators of Python. For example,operator.add(x, y)
is equivalent to the expressionx+y
. -
v7
– Assuming both listsfirst
andsecond
have same length, you do not need zip or anything else.
################
first = [1, 2, 3]
second = [4, 5, 6]
####### v1 ########
third1 = [sum(i) for i in zip(first,second)]
####### v2 ########
third2 = [x + y for x, y in zip(first, second)]
####### v3 ########
lists_of_lists = [[1, 2, 3], [4, 5, 6]]
third3 = [sum(x) for x in zip(*lists_of_lists)]
####### v4 ########
from itertools import zip_longest
third4 = list(map(sum, zip_longest(first, second, fillvalue=0)))
####### v5 ########
def sum_lists(*args):
return list(map(sum, zip(*args)))
third5 = sum_lists(first, second)
####### v6 ########
import operator
third6 = list(map(operator.add, first,second))
####### v7 ########
third7 =[first[i]+second[i] for i in range(len(first))]
####### v(i) ########
print(third1) # [5, 7, 9]
print(third2) # [5, 7, 9]
print(third3) # [5, 7, 9]
print(third4) # [5, 7, 9]
print(third5) # [5, 7, 9]
print(third6) # [5, 7, 9]
print(third7) # [5, 7, 9]
Several methods are
- Using Numpy
import numpy as np
x = np.array([2,3,3])
y = np.array([1,2,6])
print(type(x)) # <class 'numpy.ndarray'>
print(type(y)) # <class 'numpy.ndarray'>
print(x+y) # [3 5 9]
print(type(x+y)) # <class 'numpy.ndarray'>
In the above code, You can see input and output are NumPy array formats.
import numpy as np
list1=[4,2,2,5]
list2=[2,1,6,7]
print(type(list1)) # <class 'list'>
print(type(list2)) # <class 'list'>
print(np.add(list1,list2)) # [ 6 3 8 12]
print(type(np.add(list1,list2))) # <class 'numpy.ndarray'>
Here, Input and output are in different formats.
- Using Numpy add
import numpy as np
list1=[3, 1, 4]
list2=[0, 9, 7]
print(type(list1)) # <class 'list'>
print(type(list2)) # <class 'list'>
print(np.add(list1, list2).tolist()) # [3, 10, 11]
print(type(np.add(list1, list2).tolist())) # <class 'list'>
In this example, explicitly we are converting NumPy array to list type using to_list()
list1=[1, 3, 3]
list2=[3, 6, 8]
print(map(lambda x,y:x+y, list1, list2)) # <map object at 0x7fea235260a0>
print(list(map(lambda x,y:x+y, list1, list2))) # [4, 9, 11]
- Using zip and list comprehension
list1=[3, 1, 3]
list2=[1, 1, 3]
print(type(list1)) # <class 'list'>
print(type(list2)) # <class 'list'>
print(x + y for x, y in zip(list1, list2)) # <generator object <genexpr> at 0x7f755307b6d0>
print(list(x + y for x, y in zip(list1, list2))) # [4, 2, 6]
print(type([x + y for x, y in zip(list1, list2)])) # <class 'list'>
print(sum(x) for x in zip(list1, list2)) # <generator object <genexpr> at 0x7f4c623e76d0>
print(list(sum(x) for x in zip(list1, list2))) # [4, 2, 6]
print(type([sum(x) for x in zip(list1, list2)])) # <class 'list'>
- Using Map and operator.add
from operator import add
list1=[3, 1, 3]
list2=[1, 1, 3]
print(list(map(add, list1, list2))) # [4, 2, 6]