For loop 检测a'中最后一个元素的Python方法是什么;对于';环

For loop 检测a'中最后一个元素的Python方法是什么;对于';环,for-loop,python,idioms,fencepost,For Loop,Python,Idioms,Fencepost,我想知道对for循环中的最后一个元素进行特殊处理的最佳方法(更紧凑和“pythonic”的方法)。有一段代码应该只在元素之间调用,在最后一个元素中被抑制 以下是我目前的做法: 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 还有更好的办法吗

我想知道对for循环中的最后一个元素进行特殊处理的最佳方法(更紧凑和“pythonic”的方法)。有一段代码应该只在元素之间调用,在最后一个元素中被抑制

以下是我目前的做法:

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
还有更好的办法吗


注意:我不想使用诸如使用
reduce
之类的黑客攻击<代码>;)

大多数情况下,将第一次迭代作为特例而不是最后一次迭代更容易(也更便宜):

first = True
for data in data_list:
    if first:
        first = False
    else:
        between_items()

    item()
这将适用于任何iterable,即使是那些没有
len()

除此之外,我不认为有一个总体上优越的解决方案,因为它取决于你正在尝试做什么。例如,如果要从列表中构建字符串,那么使用
str.join()
自然比使用
For
循环“with special case”要好


使用相同的原理但更紧凑:

for i, line in enumerate(data_list):
    if i > 0:
        between_items()
    item()
看起来很眼熟,不是吗?:)


对于@ofko和其他确实需要找出不带
len()
的iterable的当前值是否是最后一个值的人,您需要向前看:

def lookahead(iterable):
    """Pass through all values from the given iterable, augmented by the
    information if there are more values to come after the current one
    (True), or if it is the last value (False).
    """
    # Get an iterator and pull the first value.
    it = iter(iterable)
    last = next(it)
    # Run the iterator to exhaustion (starting from the second value).
    for val in it:
        # Report the *previous* value (more to come).
        yield last, True
        last = val
    # Report the last value.
    yield last, False
然后你可以这样使用它:

>>> for i, has_more in lookahead(range(3)):
...     print(i, has_more)
0 True
1 True
2 False
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}')

如果您只是想修改
data\u list
中的最后一个元素,那么您可以简单地使用表示法:

L[-1]

然而,看起来你做的不止这些。你的方式没有什么问题。我甚至快速浏览了一些模板标记,它们基本上就是你正在做的事情。

除了最后一个元素之外,是否不可能迭代所有元素,并在循环之外处理最后一个元素?毕竟,创建一个循环是为了做一些类似于您循环的所有元素的事情;如果一个元素需要特殊的东西,它不应该在循环中

>>> for i in (1, 2, 3):
...     pass
...
>>> i
3
(另见这一问题:)


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

您的方式没有问题,除非您将有100000个循环并希望保存100000个“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
最后,一种接吻的方式来做你的事情,这将适用于任何iterable,包括那些没有
\uuu len\uuu

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

1
2
3
3

如果我想这样做,对我来说似乎很简单。

您可以在输入数据上使用滑动窗口查看下一个值,并使用哨兵检测最后一个值。这适用于任何iterable,因此您无需事先知道长度。成对实现来自


“中间代码”是头-尾模式的一个示例

您有一个项,后面是一系列(在,项之间)对。您还可以将其视为(项、项之间)对的序列,后跟一个项。一般来说,将第一个元素视为特殊元素,将所有其他元素视为“标准”情况更简单

此外,为了避免重复代码,必须提供一个函数或其他对象来包含不想重复的代码。在一个循环中嵌入一个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条件,该条件除了一次之外总是错误的。

假设输入是迭代器,这里有一种使用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.
演示:


这与Ants Aasma的方法类似,但没有使用itertools模块。它也是一个滞后的迭代器,在迭代器流中向前看一个元素:

def last_iter(it):
    # Ensure it's an iterator and get the first field
    it = iter(it)
    prev = next(it)
    for item in it:
        # Lag by one item so I know I'm not at the end
        yield 0, prev
        prev = item
    # Last item
    yield 1, prev

def test(data):
    result = list(last_iter(data))
    if not result:
        return
    if len(result) > 1:
        assert set(x[0] for x in result[:-1]) == set([0]), result
    assert result[-1][0] == 1

test([])
test([1])
test([1, 2])
test(range(5))
test(xrange(4))

for is_last, item in last_iter("Hi!"):
    print is_last, item

虽然这个问题已经很老了,但我是通过谷歌来到这里的,我发现了一个非常简单的方法:列表切片。假设您希望在所有列表条目之间放置一个“&”

s = ""
l = [1, 2, 3]
for i in l[:-1]:
    s = s + str(i) + ' & '
s = s + str(l[-1])

这将返回“1&2&3”。

使用切片和
is
检查最后一个元素:

for data in data_list:
    <code_that_is_done_for_every_element>
    if not data is data_list[-1]:
        <code_that_is_done_between_elements>
对于数据列表中的数据:
如果数据不是数据列表[-1]:

注意清空:仅当列表中的所有元素实际不同(在内存中的位置不同)时,此选项才有效。在幕后,Python可以检测相同的元素并为它们重用相同的对象。例如,对于相同值的字符串和公共整数。

如果您查看列表,对我来说,这也很有效:

for j in range(0, len(Array)):
    if len(Array) - j > 1:
        notLast()

谷歌给我带来了这个老问题,我想我可以为这个问题添加一种不同的方法

这里的大多数答案都会按照要求正确处理for循环控件,但是如果数据列表是可破坏的,我建议您从列表中弹出项目,直到得到一个空列表:

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(元素列表)。我发现这个解决方案比处理next()更优雅。

如果项目是唯一的:

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]
        #code
    for x in list[-1]:
        #code

我想到的最简单的解决办法是:

for item in data_list:
    try:
        print(new)
    except NameError: pass
    new = item
print('The last item: ' + str(new))
因此,我们总是通过延迟一次迭代来提前处理一个项目。要在第一次迭代中跳过某些操作,我只需捕获错误

当然,您需要考虑一下,以便在需要时引发
namererror

同时保留'construct'

try:
    new
except NameError: pass
else:
    # continue here if no error was raised
这依赖于之前未定义新名称。如果您患有妄想症,您可以使用以下方法确保
new
不存在:

try:
    del new
except NameError:
    pass
或者,您当然也可以使用if语句(
if-notfirst:print(new)else:notfirst=True
)。但据我所知,开销更大


所以我期待着o
try:
    del new
except NameError:
    pass
Using `timeit` yields:

    ...: try: new = 'test' 
    ...: except NameError: pass
    ...: 
100000000 loops, best of 3: 16.2 ns per loop
remaining = len(data_list)
for data in data_list:
    code_that_is_done_for_every_element

    remaining -= 1
    if remaining:
        code_that_is_done_between_elements
>>> for i in (1, 2, 3):
...     pass
...
>>> i
3
for data in data_list[:-1]:
    handle_element(data)
handle_special_element(data_list[-1])
>>> l1 = [1,5,2,3,5,1,7,43]                                                 
>>> [i for i in l1 if l1.index(i)+1==len(l1)]                               
[43]
  nrToProcess = len(list)
  for s in list:
    s.doStuff()
    nrToProcess -= 1
    if nrToProcess==0:  # this is the last one
      s.doSpecialStuff()
for i in MyList:
    # Check if 'i' is the last element in the list
    if i == MyList[-1]:
        # Do something different for the last
    else:
        # Do something for all other elements
# Count the no. of elements in the list
ListLength = len(MyList)
# Initialize a counter
count = 0

for i in MyList:
    # increment counter
    count += 1
    # Check if 'i' is the last element in the list
    # by using the counter
    if count == ListLength:
        # Do something different for the last
    else:
        # Do something for all other elements
for i,element in enumerate(list):
    if (i==len(list)-1):
        print("last element is" + element)
for data in data_list:
    code_that_is_done_for_every_element
    if data != data_list[- 1]:
        code_that_is_done_between_elements
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.')
Jakarta
Surabaya
SEMARANG