簡體   English   中英

按元素添加 2 個列表?

[英]Element-wise addition of 2 lists?

我現在有了:

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

我希望有:

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

簡單地將兩個列表按元素相加。

我當然可以迭代這兩個列表,但我不想這樣做。

這樣的最 Pythonic 的方式是什么?

使用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

其他人給出了如何在純 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開始更快。

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

正如其他人所描述的,一個快速且節省空間的解決方案是使用 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)]

在我看來,使用numpy更簡單:

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

結果:

終端執行

有關詳細的參數信息,請查看此處: numpy.add

如果您有未知數量的列表,並且沒有導入任何內容,那么這可能是 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]

也許“最 Pythonic 的方式”應該包括處理 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)

如果這是您問題中的一個函數,您可能想要哪個結果?

這很簡單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()

這適用於 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

另請參閱此相關答案並評論另一個問題

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

雖然,實際問題並不想遍歷列表來生成結果,但所有提出的解決方案都在幕后做!

刷新:如果不查看所有向量元素,則無法添加兩個向量。 因此,大多數這些解決方案的算法復雜度都是 Big-O(n)。 其中 n 是向量的維度。

因此,從算法的角度來看,使用 for 循環迭代生成結果列表也是合乎邏輯的和 Pythonic 的。 但是,除此之外,此方法沒有調用或導入任何其他庫的開銷。

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

此處顯示/討論的時間取決於系統和實現,不能作為衡量操作效率的可靠措施。 在任何情況下,向量加法運算的大 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 )]
  • zip 函數在這里很有用,與列表理解v1v2
  • 如果您有一個列表列表(而不僅僅是兩個列表),您可以使用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 - 假設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