[英]python arbitrarily incrementing an iterator inside a loop
我可能會以錯誤的方式處理此問題,但我想知道如何在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。
必須有一種更好的方法來執行此操作,希望它不涉及導入另一個模塊。
提前致謝!
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
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]在評論中指出的,如果您需要執行非常大的跳轉(例如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
示例相同的輸出。
如果您使用數字來做,列表理解可以工作:
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
不完全確定我會遵循您的思考過程,但是有一些需要注意的地方。
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(..))應該可以為您提供幫助。
您可以從迭代器中刪除值
def dropvalues(iterator, vals):
for i in xrange(vals): iterator.next()
現在,只需確保您有一個迭代器對象可以使用lines = iter(cdata.split('\\n'))
; 並遍歷它。
也許與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生成異常。
對於您的示例,由於您正在使用列表(可索引序列)而不是迭代器,因此我建議以下內容:
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
我無法解析這個問題,因為存在混亂和不相關的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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.