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中的有限经验,我只有一个解决scheme,引入一个计数器和另一个if语句。 打破循环,直到exp.match(行)为真后计数器达到5。

有一个更好的方法来做到这一点,希望不涉及导入另一个模块。

提前致谢!

Python中有一个叫itertools的神奇软件包。

但在进入之前,解释一下在Python中如何实现迭代协议就好了。 当你想提供对容器的迭代时,你需要指定提供迭代器types的__iter__()类方法。 “了解Python的”为“语句”是一篇很好的文章,介绍了for-in语句在Python中的实际工作方式,并提供了有关迭代器types如何工作的很好的概述。

看看下面的内容:

 >>> 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 。 该软件包包含用于各种迭代目的的function。 如果你需要做特殊的sorting,这是第一个研究的地方。

在底部,您可以findRecipes部分,其中包含使用现有itertools作为构build块来创build扩展工具集的配方

还有一个有趣的function正是你所需要的:

 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 

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 

例如,如果expcdata是:

 exp = re.compile(r"skip5") cdata = """ before skip skip5 1 never see it 2 ditto 3 .. 4 .. 5 after skip 6 """ 

那么输出是:


在跳过之前
 5跳过后
 6 

Python实现的C例子

 i = 0 while i < 100: if i == 50: i += 10 print i i += 1 

正如@ [Glenn Maynard]在评论中指出,如果你需要做一个非常大的跳转,例如i + = 100000000,那么你应该使用explicit 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 

这个例子产生与上面的例子相同的输出。

如果你用数字来做,列表理解可以起作用:

 for i in [x for x in range(0, 99) if x < 50 and x > 59]: print i 

把一个迭代器向前移动有点困难。 我build议事先设置你的列表,如果你不想做计数器的方法,可能是通过拆分cdata,然后找出匹配行的索引并删除该行以及下一行。 除此之外,你还是坚持反对的态度,这种态度并不像说实话那样令人不快。

另一个select是这样的:

 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 

不完全确定我遵循你的思维过程,但这里有东西饲料..

 for i in range(len(cdata.split('\n'))): if i in range(50,60): continue line = cdata[i] if exp.match(line): #increment the position of the iterator by 5? pass print line 

不知道你真的以后,但范围(len(..))应该帮助你。

您可以从迭代器中删除值

 def dropvalues(iterator, vals): for i in xrange(vals): iterator.next() 

现在只要确保你有一个迭代器对象使用lines = iter(cdata.split('\n')) ; 并循环它。

也许与基因组。 不漂亮,但…

类似的东西:

 >>> gx = (line for line in '1 2 x 3 4 5 6 7 x 9 10 11 12 x 1'.split('\n')) >>> for line in gx: ... if line == 'x': ... for i in range(2): ... line = gx.next() ... print line 

唯一的问题是确保gx可以被next()编辑。 上面的例子故意由于最后一个x而产生一个exception。

对于你的例子,因为你正在处理列表(可索引序列),而不是与迭代器,我会build议如下:

 lines = cdata.split("\n") for line in lines[:50]+lines[60:]: print line 

这不是最有效率的,因为它可能会构造3个新列表(但是如果跳过的部分比处理的部分更大,则可能比其他选项更有效),但是它非常干净和明确。

如果您不介意使用itertools模块,则可以将列表轻松转换为序列:

 from itertools import chain, islice for line in chain(islice(lines, None, 50), islice(lines, 60,None)): print line 

我无法parsing这个问题,因为有这个混乱和不相关的C代码块。 请删除它。

只关注Python代码以及如何跳过5行的问题

 lineIter= iter( cdata.splitlines() ) for line in lineIter: if exp.match(line): for count in range(5): line = lineIter.next() print line