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

我如何简化或改进它?


当前回答

我发现在循环表达式之前定义循环值很方便。对于这个方框示例,匹配循环中的值,或者其他可能需要它的地方。

numberofboxes = 1411

for j in range(1,numberofboxes):
    if j != numberofboxes - 1:
        print ("},")
    else:
        print("}")

其他回答

你的方法没有错,除非你有10万个循环,想要保存10万个“if”语句。在这种情况下,你可以这样做:

iterable = [1,2,3] # Your date
iterator = iter(iterable) # get the data iterator

try :   # wrap all in a try / except
    while 1 : 
        item = iterator.next() 
        print item # put the "for loop" code here
except StopIteration, e : # make the process on the last element here
    print item

输出:

1
2
3
3

但说真的,在你的情况下,我觉得这太过分了。

在任何情况下,你可能会更幸运的切片:

for item in iterable[:-1] :
    print item
print "last :", iterable[-1]

#outputs
1
2
last : 3

或者只是:

for item in iterable :
    print item
print iterable[-1]

#outputs
1
2
3
last : 3

最终,一个KISS的方式来做你的事情,这将适用于任何迭代对象,包括那些没有__len__的迭代对象:

item = ''
for item in iterable :
    print item
print item

Ouputs:

1
2
3
3

如果我这样做的话,对我来说很简单。

我只是遇到了这个问题,我的通用解决方案使用迭代器:

from typing import TypeVar, Iterable
E = TypeVar('E')

def metait(i: Iterable[E]) -> Iterable[tuple[E, bool, bool]]:

    first = True
    previous = None
    for elem in i:
        if previous:
            yield previous, first, False
            first = False
        previous = elem

    if previous:
        yield previous, first, True

您将收到一个元组,其中包含第一项和最后一项的原始元素和标志。它可以用于每个可迭代对象:

d = {'a': (1,2,3), 'b': (4,5,6), 'c': (7,8,9)}

for (k,v), is_first, is_last in metait(d.items()):
    print(f'{k}: {v}  {is_first} {is_last}')

这将给你:

a: (1, 2, 3)  True False
b: (4, 5, 6)  False False
c: (7, 8, 9)  False True

因此,这绝对不是“更短”的版本——如果“最短”和“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

你可以用下面的代码确定最后一个元素:

for i,element in enumerate(list):
    if (i==len(list)-1):
        print("last element is" + element)

这是一个老问题,已经有很多很好的回答了,但我觉得这很python:

def rev_enumerate(lst):
    """
    Similar to enumerate(), but counts DOWN to the last element being the
    zeroth, rather than counting UP from the first element being the zeroth.

    Since the length has to be determined up-front, this is not suitable for
    open-ended iterators.

    Parameters
    ----------
    lst : Iterable
        An iterable with a length (list, tuple, dict, set).

    Yields
    ------
    tuple
        A tuple with the reverse cardinal number of the element, followed by
        the element of the iterable.
    """
    length = len(lst) - 1
    for i, element in enumerate(lst):
        yield length - i, element

这样用:

for num_remaining, item in rev_enumerate(['a', 'b', 'c']):
    if not num_remaining:
        print(f'This is the last item in the list: {item}')

或者你想做相反的事情:

for num_remaining, item in rev_enumerate(['a', 'b', 'c']):
    if num_remaining:
        print(f'This is NOT the last item in the list: {item}')

或者,只是想知道当你走的时候还剩下多少……

for num_remaining, item in rev_enumerate(['a', 'b', 'c']):
    print(f'After {item}, there are {num_remaining} items.')

我认为现有枚举的通用性和熟悉性使其最具python性。

注意,与enumerate()不同,rev_enumerate()要求输入实现__len__,但这包括列表、元组、字典和集。