[英]How do I iterate through two lists in parallel?
我有兩個可迭代對象,我想成對對它們進行 go:
foo = [1, 2, 3]
bar = [4, 5, 6]
for (f, b) in iterate_together(foo, bar):
print("f:", f, " | b:", b)
這應該導致:
f: 1 | b: 4
f: 2 | b: 5
f: 3 | b: 6
一種方法是遍歷索引:
for i in range(len(foo)):
print("f:", foo[i], " | b:", bar[i])
但這對我來說似乎有點 unpythonic。 有更好的方法嗎?
for f, b in zip(foo, bar):
print(f, b)
當foo
或bar
中較短的一個停止時, zip
停止。
在Python 3中, zip
返回元組的迭代器,如 Python2 中的itertools.izip
。 要獲取元組列表,請使用list(zip(foo, bar))
。 要壓縮直到兩個迭代器都用完,您將使用itertools.zip_longest 。
在Python 2中, zip
返回一個元組列表。 當foo
和bar
不是很大時,這很好。 如果它們都是巨大的,那么形成zip(foo,bar)
是一個不必要的巨大臨時變量,應該用itertools.izip
或itertools.izip_longest
替換,它返回一個迭代器而不是一個列表。
import itertools
for f,b in itertools.izip(foo,bar):
print(f,b)
for f,b in itertools.izip_longest(foo,bar):
print(f,b)
izip
在foo
或bar
用盡時停止。 izip_longest
在foo
和bar
都用盡時停止。 當較短的迭代器用盡時, izip_longest
在對應於該迭代器的位置產生一個具有None
的元組。 如果您願意,您還可以設置除None
之外的其他fillvalue
。 完整的故事請看這里。
另請注意, zip
及其類似zip
的 brethen 可以接受任意數量的迭代作為參數。 例如,
for num, cheese, color in zip([1,2,3], ['manchego', 'stilton', 'brie'],
['red', 'blue', 'green']):
print('{} {} {}'.format(num, color, cheese))
印刷
1 red manchego
2 blue stilton
3 green brie
你想要zip
功能。
for (f,b) in zip(foo, bar):
print "f: ", f ,"; b: ", b
你應該使用' zip '功能。 這是您自己的 zip 函數的示例
def custom_zip(seq1, seq2):
it1 = iter(seq1)
it2 = iter(seq2)
while True:
yield next(it1), next(it2)
在@unutbu的答案的基礎上,我比較了兩個相同列表在使用 Python 3.6 的zip()
函數、Python 的enumerate()
函數、使用手動計數器(參見count()
函數)、使用索引時的迭代性能-list,以及在兩個列表之一( foo
或bar
)的元素可用於索引另一個列表的特殊情況下。 使用timeit()
函數分別研究了它們在打印和創建新列表方面的性能,其中使用的重復次數為 1000 次。 下面給出了我為執行這些調查而創建的 Python 腳本之一。 foo
和bar
列表的大小范圍從 10 到 1,000,000 個元素。
出於打印目的:在考慮 +/-5% 的精度容差后,觀察到所有考慮的方法的性能與zip()
函數大致相似。 當列表大小小於 100 個元素時發生異常。 在這種情況下,index-list 方法比zip()
函數稍慢,而enumerate()
函數要快約 9%。 其他方法產生了與zip()
函數類似的性能。
用於創建列表:探索了兩種類型的列表創建方法:使用 (a) list.append()
方法和 (b)列表理解。 在考慮到 +/-5% 的精度容差后,對於這兩種方法,發現zip()
enumerate()
比使用列表索引的函數比使用手動計數器執行得更快。 在這些比較中, zip()
函數的性能增益可以快 5% 到 60%。 有趣的是,使用foo
的元素來索引bar
可以產生與zip()
函數相同或更快的性能(5% 到 20%)。
程序員必須確定每個有意義或有意義的操作的計算時間量。
例如,出於打印目的,如果此時間標准為 1 秒,即 10**0 秒,則查看左側 1 秒處圖形的 y 軸並將其水平投影,直到到達單項式曲線,我們看到超過 144 個元素的列表大小將產生大量的計算成本和對程序員的重要性。 也就是說,本調查中提到的針對較小列表大小的方法所獲得的任何性能對程序員來說都是微不足道的。 程序員將得出結論, zip()
函數迭代打印語句的性能與其他方法相似。
在創建list
期間使用zip()
函數並行遍歷兩個列表可以獲得顯着的性能。 當並行遍歷兩個列表以打印出兩個列表的元素時, zip()
函數將產生與enumerate()
函數相似的性能,如使用手動計數器變量、使用索引列表,以及至於在兩個列表( foo
或bar
)之一的元素可用於索引另一個列表的特殊情況下。
import timeit
import matplotlib.pyplot as plt
import numpy as np
def test_zip( foo, bar ):
store = []
for f, b in zip(foo, bar):
#print(f, b)
store.append( (f, b) )
def test_enumerate( foo, bar ):
store = []
for n, f in enumerate( foo ):
#print(f, bar[n])
store.append( (f, bar[n]) )
def test_count( foo, bar ):
store = []
count = 0
for f in foo:
#print(f, bar[count])
store.append( (f, bar[count]) )
count += 1
def test_indices( foo, bar, indices ):
store = []
for i in indices:
#print(foo[i], bar[i])
store.append( (foo[i], bar[i]) )
def test_existing_list_indices( foo, bar ):
store = []
for f in foo:
#print(f, bar[f])
store.append( (f, bar[f]) )
list_sizes = [ 10, 100, 1000, 10000, 100000, 1000000 ]
tz = []
te = []
tc = []
ti = []
tii= []
tcz = []
tce = []
tci = []
tcii= []
for a in list_sizes:
foo = [ i for i in range(a) ]
bar = [ i for i in range(a) ]
indices = [ i for i in range(a) ]
reps = 1000
tz.append( timeit.timeit( 'test_zip( foo, bar )',
'from __main__ import test_zip, foo, bar',
number=reps
)
)
te.append( timeit.timeit( 'test_enumerate( foo, bar )',
'from __main__ import test_enumerate, foo, bar',
number=reps
)
)
tc.append( timeit.timeit( 'test_count( foo, bar )',
'from __main__ import test_count, foo, bar',
number=reps
)
)
ti.append( timeit.timeit( 'test_indices( foo, bar, indices )',
'from __main__ import test_indices, foo, bar, indices',
number=reps
)
)
tii.append( timeit.timeit( 'test_existing_list_indices( foo, bar )',
'from __main__ import test_existing_list_indices, foo, bar',
number=reps
)
)
tcz.append( timeit.timeit( '[(f, b) for f, b in zip(foo, bar)]',
'from __main__ import foo, bar',
number=reps
)
)
tce.append( timeit.timeit( '[(f, bar[n]) for n, f in enumerate( foo )]',
'from __main__ import foo, bar',
number=reps
)
)
tci.append( timeit.timeit( '[(foo[i], bar[i]) for i in indices ]',
'from __main__ import foo, bar, indices',
number=reps
)
)
tcii.append( timeit.timeit( '[(f, bar[f]) for f in foo ]',
'from __main__ import foo, bar',
number=reps
)
)
print( f'te = {te}' )
print( f'ti = {ti}' )
print( f'tii = {tii}' )
print( f'tc = {tc}' )
print( f'tz = {tz}' )
print( f'tce = {te}' )
print( f'tci = {ti}' )
print( f'tcii = {tii}' )
print( f'tcz = {tz}' )
fig, ax = plt.subplots( 2, 2 )
ax[0,0].plot( list_sizes, te, label='enumerate()', marker='.' )
ax[0,0].plot( list_sizes, ti, label='index-list', marker='.' )
ax[0,0].plot( list_sizes, tii, label='element of foo', marker='.' )
ax[0,0].plot( list_sizes, tc, label='count()', marker='.' )
ax[0,0].plot( list_sizes, tz, label='zip()', marker='.')
ax[0,0].set_xscale('log')
ax[0,0].set_yscale('log')
ax[0,0].set_xlabel('List Size')
ax[0,0].set_ylabel('Time (s)')
ax[0,0].legend()
ax[0,0].grid( b=True, which='major', axis='both')
ax[0,0].grid( b=True, which='minor', axis='both')
ax[0,1].plot( list_sizes, np.array(te)/np.array(tz), label='enumerate()', marker='.' )
ax[0,1].plot( list_sizes, np.array(ti)/np.array(tz), label='index-list', marker='.' )
ax[0,1].plot( list_sizes, np.array(tii)/np.array(tz), label='element of foo', marker='.' )
ax[0,1].plot( list_sizes, np.array(tc)/np.array(tz), label='count()', marker='.' )
ax[0,1].set_xscale('log')
ax[0,1].set_xlabel('List Size')
ax[0,1].set_ylabel('Performances ( vs zip() function )')
ax[0,1].legend()
ax[0,1].grid( b=True, which='major', axis='both')
ax[0,1].grid( b=True, which='minor', axis='both')
ax[1,0].plot( list_sizes, tce, label='list comprehension using enumerate()', marker='.')
ax[1,0].plot( list_sizes, tci, label='list comprehension using index-list()', marker='.')
ax[1,0].plot( list_sizes, tcii, label='list comprehension using element of foo', marker='.')
ax[1,0].plot( list_sizes, tcz, label='list comprehension using zip()', marker='.')
ax[1,0].set_xscale('log')
ax[1,0].set_yscale('log')
ax[1,0].set_xlabel('List Size')
ax[1,0].set_ylabel('Time (s)')
ax[1,0].legend()
ax[1,0].grid( b=True, which='major', axis='both')
ax[1,0].grid( b=True, which='minor', axis='both')
ax[1,1].plot( list_sizes, np.array(tce)/np.array(tcz), label='enumerate()', marker='.' )
ax[1,1].plot( list_sizes, np.array(tci)/np.array(tcz), label='index-list', marker='.' )
ax[1,1].plot( list_sizes, np.array(tcii)/np.array(tcz), label='element of foo', marker='.' )
ax[1,1].set_xscale('log')
ax[1,1].set_xlabel('List Size')
ax[1,1].set_ylabel('Performances ( vs zip() function )')
ax[1,1].legend()
ax[1,1].grid( b=True, which='major', axis='both')
ax[1,1].grid( b=True, which='minor', axis='both')
plt.show()
您可以使用理解將第 n 個元素捆綁到元組或列表中,然后使用生成器函數將它們傳遞出去。
def iterate_multi(*lists):
for i in range(min(map(len,lists))):
yield tuple(l[i] for l in lists)
for l1, l2, l3 in iterate_multi([1,2,3],[4,5,6],[7,8,9]):
print(str(l1)+","+str(l2)+","+str(l3))
這是使用列表理解的方法:
a = (1, 2, 3)
b = (4, 5, 6)
[print('f:', i, '; b', j) for i, j in zip(a, b)]
它打印:
f: 1 ; b 4
f: 2 ; b 5
f: 3 ; b 6
我們可以只使用索引來迭代......
foo = ['a', 'b', 'c']
bar = [10, 20, 30]
for indx, itm in enumerate(foo):
print (foo[indx], bar[indx])
如果要在使用zip()
一起迭代多個列表時保留索引,可以將zip
object 傳遞給enumerate()
:
for i, (f, b) in enumerate(zip(foo, bar)):
# do something
例如,如果您想打印出 2 個列表中值不同的位置,您可以執行以下操作。
foo, bar = [*'abc'], [*'aac']
for i, (f, b) in enumerate(zip(foo, bar)):
if f != b:
print(f"items at index {i} are different")
# items at index 1 are different
while a and b: # condition may change when length not equal
ae, be = a.pop(0), b.pop(0)
print(f"{ae} {be}") # check if None
制作一個 zip 對象,該對象將元組的迭代列表從列表的元素中一一生成。
像這樣 [ (arr1[0],arr2[0]), (arr1[1],arr2[1]), ....]
result=zip(arr1,arr2)
for res in result:
print(res[0],res[1])
快樂編碼。
我在 Python 中有兩個可迭代對象,我想成對地討論它們:
foo = (1, 2, 3)
bar = (4, 5, 6)
for (f, b) in some_iterator(foo, bar):
print("f: ", f, "; b: ", b)
它應該導致:
f: 1; b: 4
f: 2; b: 5
f: 3; b: 6
一種方法是迭代索引:
for i in range(len(foo)):
print("f: ", foo[i], "; b: ", bar[i])
但這對我來說似乎有點不合邏輯。 有沒有更好的方法來做到這一點?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.