如何访问上一个/下一个元素,而循环?

有没有办法访问一个列表(或元组,或其他迭代)的下一个,或以前的元素,而循环与for循环?

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

表示为发电机function:

 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 

一个简单的方法。

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

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

 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) 

查看Tempita项目的Looper工具。 它提供了一个围绕循环项的包装器对象,提供诸如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 

我知道这是旧的,但为什么不只是使用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 

如果你运行这个,你会看到它抓取前一个和下一个项目,不关心重复列表中的项目。

我不认为有一个简单的方法,特别是一个迭代器可以是一个生成器(不会回头)。 有一个体面的解决方法,依靠显式传递索引到循环体:

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

enumerate()函数是内build的。

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

枚举(迭代)可以是有用的,如果你迭代列表或元组。

以前?

你的意思是以下,对吧?

 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 

如果你想让这个解决scheme在iterables上工作,那么itertools的文档就有一个你想要的东西:

 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

不是非常pythonic,但得到它做,很简单:

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

做:保护边缘

最简单的方法是search该项目的列表:

 def get_previous(l, item): idx = l.find(item) return None if idx == 0 else l[idx-1] 

当然,这只有在列表只包含唯一的项目时才有效。 另一个解决scheme是:

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