2013-01-12 20 views
15

如果我有兩個數組的長度相同, - 說ab什麼是同時循環兩個數組的Python方法?

a = [4,6,2,6,7,3,6,7,2,5]

b = [6,4,6,3,2,7,8,5,3,5]

通常情況下,我會做到這一點,像這樣:

for i in range(len(a)): 
    print a[i] + b[i] 

,而不是東西像這樣:

i=0 
for number in a: 
    print number + b[i] 
    i += 1 

因爲我更喜歡與使用的方法一致。

我知道zip,但我從來沒有使用它。這是zip的用途嗎?

for pair in zip(a,b): 
    print pair[0] + pair[1] 

來做到這一點的Python的方式?

回答

17

如果列表ab短,用zip(如@Vincenzo PII顯示):

for x, y in zip(a, b): 
    print(x + y) 

如果列表ab很長,然後用itertools.izip以節省內存:

import itertools as IT 
for x, y in IT.izip(a, b): 
    print(x + y) 

zip創建元組列表。如果ab很大,這可能是沉重的(存儲方式)。

itertools.izip返回一個迭代器。迭代器不會生成元組的完整列表;它只會按照for循環的要求生成每個項目。因此它可以爲你節省一些記憶。

Python2在短列表中調用zip(a,b)比使用itertools.izip(a,b)快。但是在Python3中,請注意zip默認返回一個迭代器(即它相當於Python2中的itertools.izip)。


的其他變種:

+1

爲了完成這個,我還要提到'future_builtins'。 – georg

+0

所以在python3中的zip與itertools.izip相同?還是根據列表的大小而變化? – will

+2

@ will:是的,Python3中的'zip'與Python2中的'itertools.izip'相同。 (它不會改變列表大小的行爲。)要在Python3中獲得舊的'zip'行爲,請使用'list(zip(a,b))'。 – unutbu

7

一個可能的解決方案是使用zip,你提到自己,但比你如何在這個問題寫的略有不同:

for x, y in zip(a, b): 
    print x, y 

注意,元組的名單由zip()返回的長度將等於到ab的長度之間的最小值。這會影響ab的長度不一樣。

+0

這看起來很熟悉從各種示例和文檔頁面 – will

+0

這證實了pythonic :)! –

4

而不是使用zip你可以使用Numpy,特別是如果速度是重要的,你有長陣列。它的速度更快,一旦你使用numpy的數組,你不需要一個循環,可以只寫:

print a + b 

圖表顯示平均時機與總結使用拉鍊,izip和numpy的不同長度的列表: enter image description here

+1

是啊,我知道numpy。在這種情況下,它絕對適用,但我給出的例子只是一個人爲的例子。我真正想要的是當你有兩個對象列表,並且你想訪問它們的第n個對象。 當我想在'matplotlib'餅圖中將'hatch'模式添加到'wedges'時,我就明白了。最終用途就像''模式,楔形拉鍊(模式,楔子):wedge.set_hatch(模式)' – will

0

爲完整性提供此答案,因爲numpy已在另一個答案中進行了討論,並且將值從較高排列的數組中組合在一起通常很有用。

accepted answer用於秩1的任何序列/陣列工作很大然而,如果序列是多個級別(例如,numpy陣列秩2或更高的,而且如在listlist A S,或tuple),需要遍歷每個等級。下面是一個2D numpy陣列的例子:

import numpy as np 
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) 
b = np.array([list('abc'), list('pdq'), list('xyz')]) 
c = np.array([[frobnicate(aval, bval) for aval, bval in zip(arow, brow)] for arow, brow in zip(a, b)]) 

而同樣的概念適用於任何一組的相同形狀的兩個維嵌套序列的工作:

a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
b = [list('abc'), list('pdq'), list('xyz')] 
c = [[frobnicate(aval, bval) for aval, bval in zip(arow, brow)] for arow, brow in zip(a, b)] 

如果一個或兩個嵌套的序列有「漏洞」在裏面,使用itertools.zip_longest填寫孔(填充值默認爲None,但可指定):

from itertools import zip_longest as zipl 
a = [[], [4, 5, 6], [7, 8, 9]] # empty list in the first row 
b = [list('abc'), list('pdq'), []] # empty list in the last row 
c = [[frobnicate(aval, bval) for aval, bval in zipl(arow, brow)] for arow, brow in zipl(a, b)]