简体   繁体   English

按元素添加 2 个列表?

[英]Element-wise addition of 2 lists?

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?这样的最 Pythonic 的方式是什么?

Use map with operator.add :使用mapoperator.add

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

or zip with a list comprehension:或使用列表理解zip

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

The others gave examples how to do this in pure python.其他人给出了如何在纯 python 中执行此操作的示例。 If you want to do this with arrays with 100.000 elements, you should use numpy:如果要对具有 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])

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.就像在 Matlab 中一样。

Timing to compare with Ashwini's fastest version:与 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

So this is a factor 25 faster!所以这快了 25 倍! 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).对于一个简单的程序,你可能不想安装 numpy,所以使用标准的 python(我发现Henry 的版本是最 Pythonic的版本)。 If you are into serious number crunching, let numpy do the heavy lifting.如果您非常喜欢数字运算,那么让numpy完成繁重的工作。 For the speed freaks: it seems that the numpy solution is faster starting around n = 8 .对于速度怪胎:似乎 numpy 解决方案从n = 8开始更快。

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

As described by others, a fast and also space efficient solution is using numpy (np) with it's built-in vector manipulation capability:正如其他人所描述的,一个快速且节省空间的解决方案是使用 numpy (np) 及其内置的向量操作功能:

1. With Numpy 1. 使用 Numpy

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

2. With built-ins 2. 内置插件

2.1 Lambda 2.1 拉姆达

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

Notice that map() supports multiple arguments.请注意 map() 支持多个参数。

2.2 zip and list comprehension 2.2 zip 和列表理解

list1=[1, 2, 3]
list2=[4, 5, 6]
print [x + y for x, y in zip(list1, list2)]

It's simpler to use numpy from my opinion:在我看来,使用numpy更简单:

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有关详细的参数信息,请查看此处: numpy.add

Perhaps this is pythonic and slightly useful if you have an unknown number of lists, and without importing anything.如果您有未知数量的列表,并且没有导入任何内容,那么这可能是 pythonic 并且稍微有用。

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).这里 *args 接受可变数量的列表参数(但只对每个中相同数量的元素求和)。

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或者有 3 个列表

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

Output:输出:

[19, 19, 19, 19, 19]

Perhaps "the most pythonic way" should include handling the case where list1 and list2 are not the same size.也许“最 Pythonic 的方式”应该包括处理 list1 和 list2 大小不同的情况。 Applying some of these methods will quietly give you an answer.应用其中一些方法会悄悄地给你一个答案。 The numpy approach will let you know, most likely with a ValueError. numpy 方法会让您知道,最有可能是 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?如果这是您问题中的一个函数,您可能想要哪个结果?

This is simple with 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])

See doc here 在此处查看文档

If you want to receiver a python list:如果你想接收一个python列表:

result.tolist()

This will work for 2 or more lists;这适用于 2 个或更多列表; iterating through the list of lists, but using numpy addition to deal with elements of each list遍历列表列表,但使用 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))]

If you need to handle lists of different sizes, worry not!如果您需要处理不同大小的列表,请不要担心! The wonderful itertools module has you covered:精彩的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]
>>>

In Python 2, zip_longest is called izip_longest .在 Python 2 中, zip_longest被称为izip_longest

See also this relevant answer and comment on another question .另请参阅此相关答案并评论另一个问题

Use map with lambda function:将 map 与 lambda 函数一起使用:

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

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).因此,大多数这些解决方案的算法复杂度都是 Big-O(n)。 Where n is the dimension of the vector.其中 n 是向量的维度。

So, from an algorithmic point of view, using a for loop to iteratively generate the resulting list is logical and pythonic too.因此,从算法的角度来看,使用 for 循环迭代生成结果列表也是合乎逻辑的和 Pythonic 的。 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).在任何情况下,向量加法运算的大 O 复杂度是线性的,即 O(n)。

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 . zip 函数在这里很有用,与列表理解v1v2
  • If you have a list of lists (instead of just two lists) you can use v3 .如果您有一个列表列表(而不仅仅是两个列表),您可以使用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对于不同长度的列表(例如:通过在第一个/第二个列表的末尾添加 1),那么您可以尝试这样的操作(使用 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 .如果您有未知数量的相同长度的列表,您可以使用函数v5

  • v6 - The operator module exports a set of efficient functions corresponding to the intrinsic operators of Python. v6 - operator 模块导出一组与 Python 的内在运算符相对应的高效函数。 For example, operator.add(x, y) is equivalent to the expression x+y .例如, operator.add(x, y)等价于表达式x+y

  • v7 - Assuming both lists first and second have same length, you do not need zip or anything else. 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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM