如何在循环时访问上一个/下一个元素?

时间:2008-11-27 13:22:19

标签: python

有没有办法在循环使用for循环时访问列表(或元组或其他可迭代的)的下一个或前一个元素?

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

13 个答案:

答案 0 :(得分:67)

表示为生成器函数:

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

答案 1 :(得分:27)

一个简单的方法。

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

答案 2 :(得分:11)

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

>>>1

答案 3 :(得分:7)

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

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)]

在前瞻/后方使用时,如果您还需要处理数字而没有下一个或上一个值,则可能需要使用适当的值(例如无)填充序列。

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)

答案 4 :(得分:7)

我知道这已经过时了,但为什么不使用enumerate

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

如果您运行此操作,您将看到它抓取上一个和下一个项目,而不关心重复列表中的项目。

答案 5 :(得分:6)

Tempita project查看looper实用程序。它为循环项提供了一个包装器对象,它提供了诸如previous,next,first,last等属性。

看看looper类的source code,这很简单。还有其他这样的循环助手,但我现在不记得其他人了。

示例:

> 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

答案 6 :(得分:2)

我认为没有一种直截了当的方式,尤其是可迭代可以是一个生成器(不会回头)。有一个不错的解决方法,依赖于明确地将索引传递给循环体:

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

enumerate()函数是内置函数。

答案 7 :(得分:1)

迭代器只有next()方法,所以你不能向前或向后看,你只能得到下一个项目。

如果要迭代列表或元组,

枚举(iterable)可能很有用。

答案 8 :(得分:1)

马上以前?

你的意思是以下,对吧?

previous = None
for item in someList:
    if item == target: break
    previous = item
# previous is the item before the target

如果您想要 n 以前的项目,可以使用一种大小为 n 的循环队列来执行此操作。

queue = []
for item in someList:
    if item == target: break
    queue .append( item )
    if len(queue ) > n: queue .pop(0)
if len(queue ) < n: previous = None
previous = previous[0]
# previous is *n* before the target

答案 9 :(得分:1)

如果您希望解决方案适用于迭代,itertools' docs的配方可以完全符合您的要求:

import itertools

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

如果您使用的是Python 2.x,请使用itertools.izip代替zip

答案 10 :(得分:0)

我知道这是一个老问题,但是我发现显示一个简单的解决方案也很重要,该解决方案也适用于生成器和其他可迭代对象,而不像大多数答案仅适用于类似对象的列表那样。这有点类似于Brian的回答和此处的解决方案:https://www.programcreek.com/python/example/1754/itertools.tee

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)

或者,在第二个可迭代对象上调用next(如果您确定它具有至少一个元素):

import itertools

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

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

    do_something(item, next_item)

答案 11 :(得分:-2)

不是非常pythonic,但完成它并且很简单:

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

要做:保护边缘

答案 12 :(得分:-7)

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

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]