Python 如何访问for循环中的上一个/下一个元素?

Python 如何访问for循环中的上一个/下一个元素?,python,for-loop,Python,For Loop,在使用for循环时,是否有方法访问列表的下一个或上一个元素(或元组或其他iterable) l = [1, 2, 3] for item in l: if item == 2: get_previous(l, item) 迭代器只有next()方法,因此不能向前或向后看,只能获取下一项 如果要迭代列表或元组,enumerate(iterable)可能很有用。最简单的方法是在列表中搜索项: def get_previous(l, item): idx = l.fi

在使用
for
循环时,是否有方法访问
列表的下一个或上一个元素(或
元组或其他iterable)

l = [1, 2, 3]
for item in l:
    if item == 2:
        get_previous(l, item)

迭代器只有next()方法,因此不能向前或向后看,只能获取下一项


如果要迭代列表或元组,enumerate(iterable)可能很有用。

最简单的方法是在列表中搜索项:

def get_previous(l, item):
    idx = l.find(item)
    return None if idx == 0 else l[idx-1]
当然,这仅在列表仅包含唯一项时有效。另一种解决办法是:

for idx in range(len(l)):
    item = l[idx]
    if item == 2:
        l[idx-1]

我不认为有一个简单的方法,特别是因为一个iterable可以是一个(禁止返回)。您可以通过将元素的索引传递到循环体来完成此操作:

for index, item in enumerate(l):
    if index > 0:
        previous_item = l[index - 1]
    else:
        previous_item = None 

该函数是一个内置函数。

表示为生成器函数:

def neighborhood(iterable):
    iterator = iter(iterable)
    prev_item = None
    current_item = next(iterator)  # throws StopIteration if empty.
    for next_item in iterator:
        yield (prev_item, current_item, next_item)
        prev_item = current_item
        current_item = next_item
    yield (prev_item, current_item, None)
用法:

for prev,item,next in neighborhood(l):
    print prev, item, next

在处理需要某些上下文的生成器时,我经常使用下面的实用程序函数在迭代器上提供滑动窗口视图:

import collections, itertools

def window(it, winsize, step=1):
    """Sliding window iterator."""
    it=iter(it)  # Ensure we have an iterator
    l=collections.deque(itertools.islice(it, winsize))
    while 1:  # Continue till StopIteration gets raised.
        yield tuple(l)
        for i in range(step):
            l.append(it.next())
            l.popleft()
它将一次生成序列N个项目的视图,并将步骤切换到其他项目。例如

>>> list(window([1,2,3,4,5],3))
[(1, 2, 3), (2, 3, 4), (3, 4, 5)]
在前向/后向情况下使用时,如果您还需要在没有下一个或上一个值的情况下处理数字,则可能需要使用适当的值(如None)填充序列

l= range(10)
# Print adjacent numbers
for cur, next in window(l + [None] ,2):
    if next is None: print "%d is the last number." % cur
    else: print "%d is followed by %d" % (cur,next)

就在前面

你是说下面的,对吗

previous = None
for item in someList:
    if item == target: break
    previous = item
# previous is the item before the target
如果您想要n个以前的项目,可以使用大小为n的循环队列来完成

queue=[]
对于someList中的项目:
如果item==目标:中断
queue.append(项目)
如果len(queue)>n:queue.pop(0)
如果len(队列)
输出:

1

如果您要查找的项目是列表中的第一个项目,这将环绕并返回列表中的最后一个项目。换句话说,如果上面代码中的item==1:
将第三行更改为
,则会导致打印
3

从中检查活套实用程序。它在循环项周围提供一个包装器对象,该对象提供诸如previous、next、first、last等属性

看看looper类的示例,它非常简单。还有其他这样的循环助手,但我现在记不起其他的了

例如:

> easy_install Tempita
> python
>>> from tempita import looper
>>> for loop, i in looper([1, 2, 3]):
...     print loop.previous, loop.item, loop.index, loop.next, loop.first, loop.last, loop.length, loop.odd, loop.even
... 
None 1 0 2 True False 3 True 0
1 2 1 3 False False 3 False 1
2 3 2 None False True 3 True 0

虽然不是很像蟒蛇,但它很简单:

l=[1,2,3]
for index in range(len(l)):
    if l[index]==2:
        l[index-1]

要做的事情:保护边缘

我知道这很旧,但为什么不直接使用
枚举

l = ['adam', 'rick', 'morty', 'adam', 'billy', 'bob', 'wally', 'bob', 'jerry']

for i, item in enumerate(l):
    if i == 0:
        previous_item = None
    else:
        previous_item = l[i - 1]

    if i == len(l) - 1:
        next_item = None
    else:
        next_item = l[i + 1]

    print('Previous Item:', previous_item)
    print('Item:', item)
    print('Next Item:', next_item)
    print('')

    pass

如果您运行此程序,您将看到它会捕获上一个和下一个项目,而不关心列表中的重复项目。

如果您希望解决方案在iterables上运行,则有一个配方可以完全满足您的需要:

l = [1, 2, 3]

for i, j in zip(l, l[1:]):
    print(i, j)

我知道这是一个老问题,但我发现展示一个简单的解决方案很重要,这个解决方案也适用于生成器和其他类型的iterables,而不像大多数答案只适用于类似列表的对象。这与Brian的答案和这里的解决方案有些相似:

或者,在第二个iterable上调用
next
(如果您确定它至少有一个元素):


在这种情况下,我可能会执行“prev,item=item,next”。要无限地进行此循环(无停止迭代),请执行itertools import cycle中的
,并将第二行更改为:
iterator=cycle(iterable)
在这种上下文中使用enumerate是否不太像Pythonic?您要寻找的答案是Vicky Liau的,在这一行下面的一行。或者,如果您想让它在任何iterable上工作,而不仅仅是列表/元组/字符串等,只需对zip中的prev、cur、nxt执行
(l,l[1:],l[2:]):
,而不是所有这些代码。如果您需要在第一次和最后一次迭代中将
prev
nxt
设置为
None
,只需在
for
循环之前执行
l=[None,*l,None]
?这很好,不涉及外部库或特殊函数。如果一个项目重复,这不是工作不正常吗<代码>[1,2,1,3]
?@Teepeemm,是的,我会用一个符合要求的版本来更新它。我使用了这个,但扩展了以避免删除开始/结束项:
对于prev,cur,下一个在zip中([None]+l[:-1],l,l[1:+[None]):
您可以避免像这样删除开始/结束项:
l=[None,*l,None]
然后对于prev,cur,nxt-in-zip(l,l[1:],l[2:]):
链接全部断开。如果您的列表只有一个元素长
l=[2]
,这将返回与前一个元素相同的元素。如果您使用
itertools
,请使用Francisco Couzo的答案:这与@Rudiger Wolf的答案完全相同
l = ['adam', 'rick', 'morty', 'adam', 'billy', 'bob', 'wally', 'bob', 'jerry']

for i, item in enumerate(l):
    if i == 0:
        previous_item = None
    else:
        previous_item = l[i - 1]

    if i == len(l) - 1:
        next_item = None
    else:
        next_item = l[i + 1]

    print('Previous Item:', previous_item)
    print('Item:', item)
    print('Next Item:', next_item)
    print('')

    pass
l = [1, 2, 3]

for i, j in zip(l, l[1:]):
    print(i, j)
import itertools

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = itertools.tee(iterable)
    next(b, None)
    return zip(a, b)
import itertools

iter0, iter1 = itertools.tee(iterable)

for item, next_item in itertools.zip_longest(
    iter0,
    itertools.islice(iter1, 1, None)
):

    do_something(item, next_item)
import itertools

iter0, iter1 = itertools.tee(iterable)
_ = next(iter1)

for item, next_item in itertools.zip_longest(iter0, iter1):

    do_something(item, next_item)