问题:如何并行地遍历两个列表?
我在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 xrange(len(foo)):
print "f: ", foo[i], "; b: ", b[i]
但这对我来说似乎有些不可思议。有更好的方法吗?
I have two iterables in Python, and I want to go over them in pairs:
foo = (1, 2, 3)
bar = (4, 5, 6)
for (f, b) in some_iterator(foo, bar):
print "f: ", f, "; b: ", b
It should result in:
f: 1; b: 4
f: 2; b: 5
f: 3; b: 6
One way to do it is to iterate over the indices:
for i in xrange(len(foo)):
print "f: ", foo[i], "; b: ", b[i]
But that seems somewhat unpythonic to me. Is there a better way to do it?
回答 0
Python 3
for f, b in zip(foo, bar):
print(f, b)
zip
foo
或中的较短者bar
停止。
在Python 3zip
中,像itertools.izip
在Python2中一样,返回元组的迭代器。要获取元组列表,请使用list(zip(foo, bar))
。要压缩直到两个迭代器都用尽,可以使用
itertools.zip_longest。
Python 2
在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
其位置与该迭代器相对应。您还可以设置不同fillvalue
之外None
,如果你想。看到这里的完整故事。
还要注意zip
,其zip
类似brethen可以接受任意数量的Iterables作为参数。例如,
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
Python 3
for f, b in zip(foo, bar):
print(f, b)
zip
stops when the shorter of foo
or bar
stops.
In Python 3, zip
returns an iterator of tuples, like itertools.izip
in Python2. To get a list
of tuples, use list(zip(foo, bar))
. And to zip until both iterators are
exhausted, you would use
itertools.zip_longest.
Python 2
In Python 2, zip
returns a list of tuples. This is fine when foo
and bar
are not massive. If they are both massive then forming zip(foo,bar)
is an unnecessarily massive
temporary variable, and should be replaced by itertools.izip
or
itertools.izip_longest
, which returns an iterator instead of a list.
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
stops when either foo
or bar
is exhausted.
izip_longest
stops when both foo
and bar
are exhausted.
When the shorter iterator(s) are exhausted, izip_longest
yields a tuple with None
in the position corresponding to that iterator. You can also set a different fillvalue
besides None
if you wish. See here for the full story.
Note also that zip
and its zip
-like brethen can accept an arbitrary number of iterables as arguments. For example,
for num, cheese, color in zip([1,2,3], ['manchego', 'stilton', 'brie'],
['red', 'blue', 'green']):
print('{} {} {}'.format(num, color, cheese))
prints
1 red manchego
2 blue stilton
3 green brie
回答 1
您需要该zip
功能。
for (f,b) in zip(foo, bar):
print "f: ", f ,"; b: ", b
You want the zip
function.
for (f,b) in zip(foo, bar):
print "f: ", f ,"; b: ", b
回答 2
您应该使用“ zip ”功能。这是您自己的zip函数的外观示例
def custom_zip(seq1, seq2):
it1 = iter(seq1)
it2 = iter(seq2)
while True:
yield next(it1), next(it2)
You should use ‘zip‘ function. Here is an example how your own zip function can look like
def custom_zip(seq1, seq2):
it1 = iter(seq1)
it2 = iter(seq2)
while True:
yield next(it1), next(it2)
回答 3
您可以使用理解将第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))
You can bundle the nth elements into a tuple or list using comprehension, then pass them out with a generator function.
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))
回答 4
万一有人在寻找这样的东西,我发现它非常简单:
list_1 = ["Hello", "World"]
list_2 = [1, 2, 3]
for a,b in [(list_1, list_2)]:
for element_a in a:
...
for element_b in b:
...
>> Hello
World
1
2
3
列表将以其全部内容进行迭代,而zip()只会迭代最大内容长度。
In case someone is looking for something like this, I found it very simple and easy:
list_1 = ["Hello", "World"]
list_2 = [1, 2, 3]
for a,b in [(list_1, list_2)]:
for element_a in a:
...
for element_b in b:
...
>> Hello
World
1
2
3
The lists will be iterated with their full content, unlike zip() which only iterates up to the minimum content length.
回答 5
以下是使用列表理解的方法:
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
Here’s how to do it with list comprehension:
a = (1, 2, 3)
b = (4, 5, 6)
[print('f:', i, '; b', j) for i, j in zip(a, b)]
prints:
f: 1 ; b 4
f: 2 ; b 5
f: 3 ; b 6