当使用for循环迭代时,我如何处理输入的最后一个元素?特别是,如果有代码应该只出现在元素之间(而不是在最后一个元素之后),我该如何构造代码?
目前,我写的代码是这样的:
for i, data in enumerate(data_list):
code_that_is_done_for_every_element
if i != len(data_list) - 1:
code_that_is_done_between_elements
我如何简化或改进它?
您可以在输入数据上使用滑动窗口来查看下一个值,并使用哨兵来检测最后一个值。这适用于任何可迭代对象,所以你不需要事先知道它的长度。成对实现来自itertools recipes。
from itertools import tee, izip, chain
def pairwise(seq):
a,b = tee(seq)
next(b, None)
return izip(a,b)
def annotated_last(seq):
"""Returns an iterable of pairs of input item and a boolean that show if
the current item is the last item in the sequence."""
MISSING = object()
for current_item, next_item in pairwise(chain(seq, [MISSING])):
yield current_item, next_item is MISSING:
for item, is_last_item in annotated_last(data_list):
if is_last_item:
# current item is the last item
假设input是一个迭代器,下面是使用itertools中的tee和izip的方法:
from itertools import tee, izip
items, between = tee(input_iterator, 2) # Input must be an iterator.
first = items.next()
do_to_every_item(first) # All "do to every" operations done to first item go here.
for i, b in izip(items, between):
do_between_items(b) # All "between" operations go here.
do_to_every_item(i) # All "do to every" operations go here.
演示:
>>> def do_every(x): print "E", x
...
>>> def do_between(x): print "B", x
...
>>> test_input = iter(range(5))
>>>
>>> from itertools import tee, izip
>>>
>>> items, between = tee(test_input, 2)
>>> first = items.next()
>>> do_every(first)
E 0
>>> for i,b in izip(items, between):
... do_between(b)
... do_every(i)
...
B 0
E 1
B 1
E 2
B 2
E 3
B 3
E 4
>>>
“code between”是头尾模式的一个例子。
你有一个项目,后面是一系列(项目之间)对。您还可以将其视为(item, between)对的序列,后跟一个item。通常更简单的做法是将第一个元素作为特殊元素,而将所有其他元素作为“标准”情况。
此外,为了避免重复代码,必须提供一个函数或其他对象来包含不想重复的代码。在循环中嵌入if语句,除非有一次总是假的,这有点傻。
def item_processing( item ):
# *the common processing*
head_tail_iter = iter( someSequence )
head = next(head_tail_iter)
item_processing( head )
for item in head_tail_iter:
# *the between processing*
item_processing( item )
这更可靠,因为它更容易证明,它不会创建额外的数据结构(即列表的副本),也不需要大量浪费if条件的执行,if条件总是假的,只有一次例外。
您可以在输入数据上使用滑动窗口来查看下一个值,并使用哨兵来检测最后一个值。这适用于任何可迭代对象,所以你不需要事先知道它的长度。成对实现来自itertools recipes。
from itertools import tee, izip, chain
def pairwise(seq):
a,b = tee(seq)
next(b, None)
return izip(a,b)
def annotated_last(seq):
"""Returns an iterable of pairs of input item and a boolean that show if
the current item is the last item in the sequence."""
MISSING = object()
for current_item, next_item in pairwise(chain(seq, [MISSING])):
yield current_item, next_item is MISSING:
for item, is_last_item in annotated_last(data_list):
if is_last_item:
# current item is the last item