我有这段代码
for iline, line in enumerate(lines):
...
if <condition>:
<skip 5 iterations>
正如您所读的,我想让for循环在满足条件时跳过5次迭代。如果条件得以满足,我可以确定"lines"对象中还剩下5个或更多的物体。
"lines"由一组字典数组组成,必须按顺序进行循环遍历。
iline = 0
while iline < len(lines):
line = lines[iline]
if <condition>:
place_where_skip_happened = iline
iline += 5
iline += 1
如果您正在迭代文件对象,可以使用next跳过行,或者将行作为迭代器:
lines = iter(range(20))
for l in lines:
if l == 10:
[next(lines) for _ in range(5)]
print(l)
0
1
2
3
4
5
6
7
8
9
10
16
17
18
19
这真的取决于你正在迭代的内容以及你想要做什么。
from itertools import islice
it = iter(enumerate(lines))
for iline, line in it:
if <condition>:
place_where_skip_happened = iline
next(islice(it,5 ,5), None)
print(line)
itertools.islice
函数跳过行 https://docs.python.org/2/library/itertools.html#itertools.islice - Padraic Cunningham这种做法的标准惯用语是创建一个迭代器,然后使用其中的一种消费模式(见这里在itertools
文档中)。
例如:
from itertools import islice
lines = list("abcdefghij")
lit = iter(enumerate(lines))
for iline, line in lit:
print(iline, line)
if line == "c":
# skip 3
next(islice(lit, 3,3), None)
生成
0 a
1 b
2 c
6 g
7 h
8 i
9 j
类似于被接受的答案...... 但不使用 itertools
(在我看来,islice
不会提高可读性),另外 enumerate()
已经返回一个迭代器,所以你根本不需要 iter()
:
lines = [{str(x): x} for x in range(20)] # dummy data
it = enumerate(lines)
for i, line in it:
print(line)
if i == 10: # condition using enumeration index
[next(it, None) for _ in range(5)] # skip 5
最后一行可以选择扩展以提高可读性:
for _ in range(5): # skip 5
next(it, None)
next()
中的None
参数可以避免由于不够跳过的元素而导致的异常。(对于原始问题,它可以被省略,因为OP写道:"我可以确定,如果条件得到满足,在lines
对象中仍有5个或更多的对象。")
如果跳过条件不是基于枚举索引,只需将列表作为FIFO队列处理,并使用pop()
从中消耗:
lines = [{str(x): x} for x in range(20)] # dummy data
while lines:
line = lines.pop(0) # get first item
print(line)
if <condition>: # some other kind of condition
[lines.pop(0) for _ in range(5)] # skip 5
与之前相同,最后一行可选扩展以提高可读性:
for _ in range(5): # skip 5
lines.pop(0)
collections.deque
以提高性能。)您可以使用递归的函数式编程风格,首先将 for
循环的必要部分放入一个函数中:
def my_function(iline, line, rest_of_lines, **other_args):
do_some_side_effects(iline, line, **other_args)
if rest_of_lines == []:
return <some base case>
increment = 5 if <condition> else 1
return my_function(iline+increment,
rest_of_lines[increment-1],
rest_of_lines[increment:],
**other_args)
如果函数不需要返回任何内容,你可以将代码行调整为函数调用,并且返回结果将为None
。
然后你需要在某个地方调用它:
other_args = get_other_args(...)
my_function(0, lines[0], lines[1:], **other_args)
do_some_side_effects
的内部结果传回递归函数调用中,以便它可以构建出结果。def my_function(iline, line, rest_of_lines, output, **other_args):
some_value = do_some_side_effects(iline, line, **other_args)
new_output = put_value_in_output(some_value, output)
# could be as simple as appending to a list/inserting to a dict
# or as complicated as you want.
if rest_of_lines == []:
return new_output
increment = 5 if <condition> else 1
return my_function(iline+increment,
rest_of_lines[increment-1],
rest_of_lines[increment:],
new_output,
**other_args)
other_args = get_other_args(...)
empty_output = get_initial_data_structure(...)
full_output = my_function(0, lines[0], lines[1:], empty_output, **other_args)
while
循环,尽管我倾向于组织我的项目和API,以便使用递归函数方法仍然是高效且易读的。 我还会尝试不要在循环内允许副作用。iline = 0
skip = {True:5, False:1}
while iline > len(lines):
line = lines[iline]
...
iline += skip[condition]
使用外部标志,在满足条件时设置它,并在循环开始时检查它:
ignore = 0
for iline, line in enumerate(lines):
if ignore > 0:
ignore -= 1
continue
print(iline, line)
if iline == 5:
ignore = 5
或者明确地从枚举中提取5个元素:
enum_lines = enumerate(lines)
for iline, line in enum_lines:
print(iline, line)
if iline == 5:
for _, _ in zip(range(5), enum_lines):
pass
我个人更喜欢第一种方法,但第二种方法看起来更符合Python的风格。
while
循环会更有效率。 - Tanveer Alamcontinue
命令将循环移动到下一个可迭代对象。 - kilojoules