Python: 优雅地对同一列表进行双重/多重迭代的方法
我写了一段代码,目的是比较列表中的某些项目和后面其他项目之间的关系。请问有没有更优雅的方式来处理这种双重循环的情况?
jump_item_iter = (j for j in items if some_cond)
try:
jump_item = jump_item_iter.next()
except StopIteration:
return
for item in items:
if jump_item is item:
try:
jump_item = jump_iter.next()
except StopIteration:
return
# do lots of stuff with item and jump_item
我觉得“except StopIteration
”这个写法不太优雅。
编辑:
为了让这个问题更清楚,我想遍历列表中的每个项目,并将它与列表中后面某个满足条件的项目(称为jump_item)配对。
17 个回答
1
我不知道 compare()
这个函数具体在干嘛,但大部分情况下(大约80%),你可以用一个简单的字典或者一对字典来解决问题。在一个列表里跳来跳去其实就是一种线性搜索。线性搜索尽量应该用直接引用(比如字典)或者树搜索(使用 bisect 模块)来替代。
1
下面这个迭代器在时间和内存使用上都很高效:
def jump_items(items):
number_to_be_returned = 0
for elmt in items:
if <condition(elmt)>:
for i in range(number_to_be_returned):
yield elmt
number_to_be_returned = 1
else:
number_to_be_returned += 1
for (item, jump_item) in zip(items, jump_items(items)):
# do lots of stuff
请注意,你可能实际上想把第一个返回的数字设置为1...
4
从我所看到的,现有的解决方案都适用于一次性使用的迭代器,可能是无限的,但它们似乎都需要一个可迭代的对象。
这里有一个解决方案。
def batch_by(condition, seq):
it = iter(seq)
batch = [it.next()]
for jump_item in it:
if condition(jump_item):
for item in batch:
yield item, jump_item
batch = []
batch.append(jump_item)
这个方法可以轻松处理无限迭代器:
from itertools import count, islice
is_prime = lambda n: n == 2 or all(n % div for div in xrange(2,n))
print list(islice(batch_by(is_prime, count()), 100))
这个代码会打印出前100个整数以及跟在它们后面的质数。