在循环中任意增量化Python迭代器
我可能走错了方向,但我想知道在Python中该怎么处理这个问题。
首先看一些C语言的代码:
int i;
for(i=0;i<100;i++){
if(i == 50)
i = i + 10;
printf("%i\n", i);
}
好吧,我们从来没有看到50这个数字……
我的问题是,怎样在Python中做类似的事情呢?比如:
for line in cdata.split('\n'):
if exp.match(line):
#increment the position of the iterator by 5?
pass
print line
根据我在Python中的有限经验,我只有一个解决方案,就是引入一个计数器和另一个if语句。也就是说,直到计数器达到5,才会在exp.match(line)为真的时候跳出循环。
肯定还有更好的方法来做到这一点,希望不需要导入其他模块。
提前谢谢大家!
8 个回答
如果你是用数字的话,列表推导式可以很好用:
for i in [x for x in range(0, 99) if x < 50 and x > 59]:
print i
不过,向前移动一个迭代器就有点复杂了。如果你不想用计数器的方法,我建议你提前准备好列表,可能可以通过拆分cdata来实现,然后找出匹配行的索引,删除那一行和后面的行。除此之外,你就只能用计数器的方法了,老实说,这并没有你想象的那么麻烦。
还有一个选择是这样的:
iterator = iter(cdata.split('\n'))
for line in iterator:
if exp.match(line):
for i in range(0, 5):
try:
iterator.next()
except StopIteration:
break
else:
print line
itertools.islice:
lines = iter(cdata.splitlines())
for line in lines:
if exp.match(line):
#increment the position of the iterator by 5
for _ in itertools.islice(lines, 4):
pass
continue # skip 1+4 lines
print line
举个例子,如果 exp
和 cdata
是:
exp = re.compile(r"skip5")
cdata = """
before skip
skip5
1 never see it
2 ditto
3 ..
4 ..
5 after skip
6
"""
那么输出结果是:
before skip 5 after skip 6
Python实现C语言的例子
i = 0
while i < 100:
if i == 50:
i += 10
print i
i += 1
正如 @[Glenn Maynard] 在评论中提到的,如果你需要跳得很大,比如 i += 100000000,那就应该使用明确的 while
循环,而不是在 for
循环中跳过某些步骤。
下面是一个使用明确的 while
循环的例子,而不是 islice
:
lines = cdata.splitlines()
i = 0
while i < len(lines):
if exp.match(lines[i]):
#increment the position of the iterator by 5
i += 5
else:
print lines[i]
i += 1
这个例子产生的输出和上面的 islice
例子是一样的。
在Python中,有一个非常棒的库叫做 itertools
。
不过在介绍这个库之前,先来简单说说Python是怎么处理循环的。当你想要让你的容器(比如列表或字典)可以被循环访问时,你需要定义一个叫做 __iter__()
的方法,这个方法会返回一个 迭代器。有一篇不错的文章 “理解Python的'for'语句”,详细讲解了 for-in
语句是如何在Python中工作的,并且提供了关于迭代器的很好的概述。
看看下面的例子:
>>> sequence = [1, 2, 3, 4, 5]
>>> iterator = sequence.__iter__()
>>> iterator.next()
1
>>> iterator.next()
2
>>> for number in iterator:
print number
3
4
5
现在回到 itertools
。这个库里面有很多函数,可以用来处理各种循环需求。如果你需要做一些特殊的序列操作,这里是你首先要查看的地方。
在页面底部,你可以找到 食谱部分,这里有一些 使用现有的itertools作为基础工具集创建扩展工具集的食谱。
还有一个有趣的函数,正好能满足你的需求:
def consume(iterator, n):
'''Advance the iterator n-steps ahead. If n is none, consume entirely.'''
collections.deque(itertools.islice(iterator, n), maxlen=0)
这里有一个简单易懂的例子,展示它是如何工作的 (Python 2.5):
>>> import itertools, collections
>>> def consume(iterator, n):
collections.deque(itertools.islice(iterator, n))
>>> iterator = range(1, 16).__iter__()
>>> for number in iterator:
if (number == 5):
# Disregard 6, 7, 8, 9 (5 doesn't get printed just as well)
consume(iterator, 4)
else:
print number
1
2
3
4
10
11
12
13
14
15