逐元素添加两个列表?
- 2024-12-18 08:38:00
- admin 原创
- 176
问题描述:
我现在有:
list1 = [1, 2, 3]
list2 = [4, 5, 6]
我希望拥有:
[1, 2, 3]
+ + +
[4, 5, 6]
|| || ||
[5, 7, 9]
只需将两个列表逐个元素相加即可。
我当然可以迭代这两个列表,但我不想这样做。
最符合 Python 风格的方式是什么?
解决方案 1:
使用: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
解决方案 2:
其他人给出了如何在纯 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(我发现Henry 的版本是最 Pythonic 的版本)。如果您喜欢严肃的数字运算,那就让我们numpy
来做繁重的工作吧。对于速度狂人来说:似乎从 开始 numpy 解决方案更快n = 8
。
解决方案 3:
[a + b for a, b in zip(list1, list2)]
解决方案 4:
正如其他人所描述的,一种快速且节省空间的解决方案是使用具有内置矢量操作功能的 numpy (np):
1.使用 Numpy
x = np.array([1,2,3])
y = np.array([2,3,4])
print x+y
2. 内置功能
2.1 Lambda
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)]
解决方案 5:
从我的观点来看,它使用起来更简单numpy
:
import numpy as np
list1=[1,2,3]
list2=[4,5,6]
np.add(list1,list2)
结果:
有关详细参数信息,请查看此处:numpy.add
解决方案 6:
如果您有未知数量的列表,并且不需要导入任何内容,那么这也许是 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]
解决方案 7:
也许“最符合 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)
如果这是你问题中的一个函数,你可能想要什么结果?
解决方案 8:
如果您需要处理不同大小的列表,请不要担心!出色的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
。
另请参阅此相关答案并评论另一个问题。
解决方案 9:
这很简单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])
请参阅此处的文档
如果你想接收一个python列表:
result.tolist()
解决方案 10:
这将适用于 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]
解决方案 11:
[list1[i] + list2[i] for i in range(len(list1))]
解决方案 12:
将 map 与 lambda 函数结合使用:
>>> map(lambda x, y: x + y, list1, list2)
[5, 7, 9]
解决方案 13:
我没有计时,但我猜测这会很快:
import numpy as np
list1=[1, 2, 3]
list2=[4, 5, 6]
list_sum = (np.add(list1, list2)).tolist()
[5, 7, 9]
解决方案 14:
zip 函数在这里很有用,与列表推导一起使用
v1
。v2
如果您有一个列表列表(而不是仅仅两个列表),则可以使用
v3
。对于长度不同的列表(例如:通过在第一个/第二个列表的末尾添加 1),那么您可以尝试这样的操作(使用 zip_longest)-
v4
first = [1, 2, 3, 1]
second = [4, 5, 6]
output: [5, 7, 9, 1]
如果有未知数量的相同长度的列表,则可以使用函数
v5
。v6
- operator 模块导出一组与 Python 固有运算符相对应的高效函数。例如,operator.add(x, y)
相当于表达式x+y
。v7
- 假设两个列表的长度first
相同second
,则不需要 zip 或其他任何东西。
first = [1, 2, 3]
second = [4, 5, 6]
# v1: Using list comprehension and sum function
# Simply an element-wise addition of two lists.
# Pythonic approach leveraging list comprehension and sum function.
third1 = [sum(i) for i in zip(first, second)]
# v2: Using list comprehension and element-wise addition
# Simply an element-wise addition of two lists.
# Pythonic approach using list comprehension with element-wise addition.
third2 = [x + y for x, y in zip(first, second)]
# v3: Using list comprehension and sum function with unpacking
# Simply an element-wise addition of two lists.
# Pythonic approach utilizing list comprehension, sum function, and unpacking.
lists_of_lists = [[1, 2, 3], [4, 5, 6]]
third3 = [sum(x) for x in zip(*lists_of_lists)]
# v4: Using map, zip_longest, and sum function
# Simply an element-wise addition of two lists.
# Pythonic approach using map, zip_longest for equal-length iteration, and sum function.
from itertools import zip_longest
third4 = list(map(sum, zip_longest(first, second, fillvalue=0)))
# v5: Using a custom function and zip with *args
# Simply an element-wise addition of two lists.
# Pythonic approach with a custom function using zip and *args for flexibility.
def sum_lists(*args):
return list(map(sum, zip(*args)))
third5 = sum_lists(first, second)
# v6: Using map, operator.add, and element-wise addition
# Simply an element-wise addition of two lists.
# Pythonic approach leveraging map, operator.add for element-wise addition.
import operator
third6 = list(map(operator.add, first, second))
# v7: Using list comprehension and range-based indexing
# Simply an element-wise addition of two lists.
# Pythonic approach using list comprehension with range-based indexing.
third7 = [first[i] + second[i] for i in range(len(first))]
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]
解决方案 15:
尽管实际问题并不想遍历列表来生成结果,但所有提出的解决方案实际上都是这样做的!
回顾一下:如果不考虑所有向量元素,就无法将两个向量相加。因此,大多数此类解决方案的算法复杂度都是 Big-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)。
解决方案 16:
有几种方法
使用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'>
这里,输入和输出的格式不同。
使用 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 数组转换为列表类型
使用Map和Lambda
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]
使用zip和列表推导
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'>
使用Map和operator.add
from operator import add
list1=[3, 1, 3]
list2=[1, 1, 3]
print(list(map(add, list1, list2))) # [4, 2, 6]
解决方案 17:
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 )]
解决方案 18:
list1 = [1, 2, 3]
list2 = [4, 5, 6]
[list1_i + list2_i for list1_i, list2_i in zip(list1 , list2)]
>> [5, 7, 9]
只需添加减法,因为减法只不过是负和。那么解决方案将是:
[list1_i - list2_i for list1_i, list2_i in zip(list1 , list2)]
>> [-3, -3, -3]
扫码咨询,免费领取项目管理大礼包!