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语句。 中断循环,直到exp.match(line)为true后计数器达到5。
必须有一种更好的方法来执行此操作,希望它不涉及导入另一个模块。
提前致谢!
jr0d asked 2020-06-25T22:20:57Z
8个解决方案
44 votes
Python中有一个很棒的软件包,名为itertools。
但是在开始之前,它很好地解释了如何在Python中实现迭代协议。 当要在容器上提供迭代时,请指定提供迭代器类型的itertools类方法。 “了解Python的'for'语句”是一篇不错的文章,介绍了293913273348391010144语句在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
Filip Dupanović answered 2020-06-25T22:21:35Z
16 votes
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
例如,如果islice、islice是:
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]在评论中指出的,如果您需要执行非常大的跳转(例如i + = 100000000),则应使用显式islice循环,而不是仅跳过islice循环中的步骤。
这是使用显式islice循环而不是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示例相同的输出。
jfs answered 2020-06-25T22:22:21Z
2 votes
如果您使用数字来做,列表理解可以工作:
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
Benno answered 2020-06-25T22:22:50Z
1 votes
不完全确定我会遵循您的思考过程,但是有一些需要注意的地方。
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
不确定您真正追求的是什么,但是range(len(..))应该可以为您提供帮助。
rh0dium answered 2020-06-25T22:23:15Z
1 votes
您可以从迭代器中删除值
def dropvalues(iterator, vals):
for i in xrange(vals): iterator.next()
现在只需确保您有一个迭代器对象可用于lines = iter(cdata.split('\n')); 并遍历它。
u0b34a0f6ae answered 2020-06-25T22:23:39Z
0 votes
也许与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()编辑。 上面的示例故意由于最后一个x生成异常。
mjv answered 2020-06-25T22:24:08Z
0 votes
对于您的示例,由于您正在使用列表(可索引序列)而不是迭代器,因此我建议以下内容:
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
fortran answered 2020-06-25T22:24:37Z
-6 votes
我无法解析这个问题,因为这里存在混乱且无关的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
S.Lott answered 2020-06-25T22:25:01Z