按元素添加2个列表?

我现在有:

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

我希望有:

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

仅仅是两个列表的元素相加。

我当然可以迭代这两个列表,但我不想这样做。

这样做的最python的方式是什么?

392959 次浏览

使用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
[a + b for a, b in zip(list1, list2)]

其他人给出了如何在纯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(我发现亨利的版本是最python的)。如果你需要处理严重的数字,让numpy来做繁重的工作。对于速度狂人:似乎numpy解决方案在n = 8附近开始更快。

也许“最python化的方式”应该包括处理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)

如果这是你问题中的函数你想要什么结果?

使用map与lambda函数:

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

我还没有计时,但我怀疑这将是相当快的:

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


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


[5, 7, 9]

这将适用于2个或更多的列表;遍历列表的列表,但使用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]
[list1[i] + list2[i] for i in range(len(list1))]

如果您需要处理不同大小的列表,不用担心!精彩的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_longest被称为izip_longest

另见这个相关的回答和评论另一个问题

正如其他人所描述的那样,一个快速且节省空间的解决方案是使用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)]

虽然,实际的问题并不想遍历列表来生成结果,但是所提出的所有解决方案实际上都是这样做的!

要刷新:如果不查看所有向量元素,就不能将两个向量相加。因此,大多数解的算法复杂度都是大o (n)。其中n是向量的维数。

因此,从算法的角度来看,使用for循环迭代生成结果列表是合乎逻辑的,也是python化的。但是,除此之外,该方法没有调用或导入任何附加库的开销。

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

这里显示/讨论的时间取决于系统和实现,不能作为衡量操作效率的可靠措施。在任何情况下,向量加法运算的大O复杂度是线性的,即O(n)。

在我看来,使用numpy更简单:

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

结果:

终端执行

有关详细参数信息,请查看这里:numpy.add

这在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

如果你想接收一个python列表:

result.tolist()

如果您有一个未知数量的列表,并且没有导入任何东西,那么这可能是python式的,稍微有用一些。

只要列表的长度相同,就可以使用下面的函数。

这里*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]
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 )]
  • zip函数在这里很有用,与列表理解v1v2一起使用。
  • 如果你有一个列表的列表(而不是两个列表),你可以使用v3
  • 对于不同长度的列表(例如:通过在第一个/第二个列表的末尾添加1),那么您可以尝试这样做(使用zip_longest) - v4
first = [1, 2, 3, 1]
second = [4, 5, 6]


output: [5, 7, 9, 1]
  • 如果你有一个未知数量的相同长度的列表,你可以使用函数v5

  • v6 -操作符模块导出一组有效的函数,对应于Python的内在操作符。例如,operator.add(x, y)等价于表达式x+y

  • v7 -假设两个列表firstsecond都有相同的长度,你不需要zip或其他任何东西。

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

有几种方法

  1. 使用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'>

在上面的代码中,你可以看到输入和输出都是NumPy数组格式。

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

这里输入和输出是不同的格式。

  1. 使用Numpy 添加
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'>

在本例中,我们显式地使用to_list ()将NumPy数组转换为列表类型

  1. 使用地图λ
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]
  1. 使用邮政编码列表理解
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'>
  1. 使用地图operator.add
from operator import add
list1=[3, 1, 3]
list2=[1, 1, 3]
print(list(map(add, list1, list2))) # [4, 2, 6]