当使用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
我如何简化或改进它?
我在下面分享了两个简单的方法来查找循环的结束。
方法1:
num_list = [1, 2, 3, 4]
for n in num_list:
if num_list[-1] == n:
print('this is the last iteration of the loop')
方法2:
num_list = [1, 2, 3, 4]
loop_count = len(num_list) - 1 # 3
for index, num in enumerate(num_list):
if index == loop_count:
print('this is the last iteration of the loop')
我将提供一种更优雅和健壮的方式,如下所示,使用unpacking:
def mark_last(iterable):
try:
*init, last = iterable
except ValueError: # if iterable is empty
return
for e in init:
yield e, True
yield last, False
测试:
for a, b in mark_last([1, 2, 3]):
print(a, b)
结果是:
1真正的
2真
3错误
因此,这绝对不是“更短”的版本——如果“最短”和“Pythonic”实际上是兼容的,人们可能会离题。
但如果经常需要这种模式,就把逻辑放到a中
10行生成器-并获得与元素相关的任何元数据
在for调用中直接定位。这里的另一个优势是它会
适用于任意可迭代对象,而不仅仅是序列。
_sentinel = object()
def iter_check_last(iterable):
iterable = iter(iterable)
current_element = next(iterable, _sentinel)
while current_element is not _sentinel:
next_element = next(iterable, _sentinel)
yield (next_element is _sentinel, current_element)
current_element = next_element
In [107]: for is_last, el in iter_check_last(range(3)):
...: print(is_last, el)
...:
...:
False 0
False 1
True 2
“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条件总是假的,只有一次例外。
谷歌让我想到了这个老问题,我想我可以用不同的方法来解决这个问题。
这里的大多数答案将处理一个正确的处理for循环控件,但如果data_list是可销毁的,我建议你从列表中弹出项目,直到你得到一个空列表:
while True:
element = element_list.pop(0)
do_this_for_all_elements()
if not element:
do_this_only_for_last_element()
break
do_this_for_all_elements_but_last()
如果不需要对最后一个元素做任何操作,甚至可以使用while len(element_list)。我发现这个解决方案比处理next()更优雅。