当使用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

我如何简化或改进它?


当前回答

我将提供一种更优雅和健壮的方式,如下所示,使用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错误

其他回答

您可以在输入数据上使用滑动窗口来查看下一个值,并使用哨兵来检测最后一个值。这适用于任何可迭代对象,所以你不需要事先知道它的长度。成对实现来自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

如果你乐意用这个清单来破坏,那么下面就是。 为了加快从O(n²)到O(n)的过程,我们将反转列表,因为pop(0)每次迭代都会移动列表——参见下面Nicholas Pipitone的评论

data_list.reverse()
while data_list:
   value = data_list.pop()
   code_that_is_done_for_every_element(value)
   if data_list:
       code_that_is_done_between_elements(value)
   else:
       code_that_is_done_for_last_element(value)


这适用于空列表和非唯一项的列表。 因为列表通常是暂时的,所以这种方法非常有效……以销毁列表为代价。

是否不可能遍历除最后一个元素以外的所有元素,并在循环之外处理最后一个元素?毕竟,创建循环的目的与循环遍历的所有元素类似;如果一个元素需要一些特殊的东西,它就不应该在循环中。

(另请参阅这个问题:循环中的最后一个元素是否值得单独处理)

编辑:因为这个问题更多的是关于“中间”,所以要么第一个元素是特殊的,因为它没有前一个元素,要么最后一个元素是特殊的,因为它没有后继元素。

如果项目是唯一的:

for x in list:
    #code
    if x == list[-1]:
        #code

其他选项:

pos = -1
for x in list:
    pos += 1
    #code
    if pos == len(list) - 1:
        #code


for x in list:
    #code
#code - e.g. print x


if len(list) > 0:
    for x in list[:-1]:
        #process everything except the last element
    for x in list[-1:]:
        #process only last element

有多种方法。切片是最快的。再添加一个使用.index()方法的:

>>> l1 = [1,5,2,3,5,1,7,43]                                                 
>>> [i for i in l1 if l1.index(i)+1==len(l1)]                               
[43]