python任意增加循环内的迭代器

时间:2009-09-24 23:11:18

标签: python iterator

我可能以错误的方式解决这个问题,但我想知道如何在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语句。在exp.match(line)为真之后,打破循环直到计数器达到5。

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

提前致谢!

8 个答案:

答案 0 :(得分:43)

Python中有一个名为itertools的精彩软件包。

但在我进入之前,它很适合解释如何在Python中实现迭代协议。如果要对容器进行迭代,请指定提供__iter__()iterator type类方法。 "Understanding Python's 'for' statement"是一篇很好的文章,涵盖了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。该包包含用于各种迭代目的的函数。如果您需要进行特殊排序,这是第一个要研究的地方。

在底部,您可以找到包含配方的Recipes部分,以使用现有的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

答案 1 :(得分:16)

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 

C实例的Python实现

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

正如@ [Glenn Maynard]在the comment中指出的,如果你需要做一个非常大的跳跃,比如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示例相同的输出。

答案 2 :(得分:2)

如果您正在使用数字,列表理解可以起作用:

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

答案 3 :(得分:1)

我不完全确定我是否遵循了您的思维过程,但这里有一些可供选择的东西..

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(..))可以帮助你。

答案 4 :(得分:1)

您可以从迭代器中删除值

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

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

答案 5 :(得分:0)

也许使用genexps。不漂亮但是......

类似的东西:

>>> 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() - ed。由于最后一个x,上面的例子故意产生一个异常。

答案 6 :(得分:0)

对于您的示例,当您使用列表(可索引序列)而不使用迭代器时,我建议使用以下内容:

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

答案 7 :(得分:-6)

我无法解析这个问题差异很大,因为存在这个令人困惑和无关的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