依次迭代两个列表

30

我有两个数字列表list1list2,我想使用相同的指令对它们进行迭代。就像这样:

for item in list1:
  print(item.amount)
  print(item.total_amount)

for item in list2:
  print(item.amount)
  print(item.total_amount)

但这感觉有点多余。我知道我可以写for item in list1 + list2:,但这会付出运行时间的代价。

有没有一种方法可以在不浪费时间的情况下做到这一点?

4个回答

47

这可以使用itertools.chain 来实现:

import itertools

l1 = [1, 2, 3, 4]
l2 = [5, 6, 7, 8]

for i in itertools.chain(l1, l2):
    print(i, end=" ")

将打印:

1 2 3 4 5 6 7 8 
根据文档,chain 的作用如下:
制作一个迭代器,从第一个可迭代对象返回元素,直到耗尽,然后继续到下一个可迭代对象,直到所有可迭代对象都耗尽。
如果您的列表在一个列表中,则可以使用itertools.chain.from_iterable
l = [l1, l2]
for i in itertools.chain.from_iterable(l):
    print(i, end=" ")

这会产生相同的结果。

如果你不想为此导入一个模块,编写一个函数也很简单:

def custom_chain(*it):
    for iterab in it:
        yield from iterab

这需要使用Python 3,对于Python 2,只需使用一个循环将它们yield回去:

def custom_chain(*it):
    for iterab in it:
        for val in iterab:
            yield val

除了之前提到的,Python 3.5 还可以在列表字面量中拆包:

for i in [*l1, *l2]:
    print(i, end=" ")

虽然这比l1 + l2略快,但仍会构建一个列表,然后将其丢弃; 仅在最后作为解决方案。


如果我在循环中添加一个带有“break”的“if”条件,并且它会在第一个列表中触发,那么第二个列表就不会运行,对吗? - Marosinho

14

chain函数可以使用,但是如果你认为为了调用单个函数而导入一个模块会显得过于繁琐,你可以在代码中直接实现它的功能:

for seq in (list1, list2):
  for item in seq:
    print(item.amount)
    print(item.total_amount)

创建 (list1, list2) 元组的时间复杂度是 O(1),与列表长度无关,因此与将列表连接起来相比,它应该具有更好的性能。

0

经过多次执行,第二种方法是最快的选择。

import itertools
from time import time

l1 = list(range(1000))
l2 = list(range(1000))

print('Alternative 1. Itertools')
t = time()
for j in range(10000):
    s = 0
    for i in itertools.chain(l1, l2):
        s += i
print(time() - t)

print('Alternative 2. Naive')
t = time()
for j in range(10000):
    s = 0
    for i in [*l1, *l2]:
        s += i
print(time() - t)

print('Alternative 3. Yield')
def chain(*ls):
    for l in ls:
        for k in l:
            yield k
t = time()
for j in range(10000):
    s = 0
    for i in chain(l1, l2):
        s += i
print(time() - t)

0
这样怎么样:
for item in list1 + list2:
    print(item.amount)
    print(item.total_amount)

只有3行


3
我认为这会将列表连接成一个新创建的列表,这样会很耗费资源。 - Ustaman Sangat
5
从这个问题中:"我知道我可以写for item in list1 + list2:" - jonrsharpe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接