我可能以错误的方式解决这个问题,但我想知道如何在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。
必须有更好的方法来做到这一点,希望不涉及导入另一个模块。
提前致谢!
答案 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)
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
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