2008-11-27 18 views

Respuesta

0

iteradores sólo tienen el método next() por lo que no puede mirar hacia delante o hacia atrás, sólo se puede obtener el siguiente artículo.

enumerar (iterable) puede ser útil si está iterando una lista o tupla.

-7

La forma más sencilla es buscar en la lista para el artículo:

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

Por supuesto, esto sólo funciona si la lista sólo contiene artículos únicos. La otra solución es:

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

No creo que hay una manera sencilla, sobre todo que un iterable puede ser un generador (no hay vuelta atrás). Hay una solución decente, confiando en que pasa explícitamente el índice en el cuerpo del bucle:

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

La función enumerate() es una orden interna.

61

Expresado como una función de generador:

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) 

Uso:

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

Podría hacer "prev, item = item, next" en este caso. –

+1

Para hacer este ciclo infinitamente (sin StopIteration), haga 'from itertools import cycle' y cambie la segunda línea a:' iterator = cycle (iterable) ' –

+0

¿Es menos pitónico utilizar enumerate en este contexto? – batbrat

6

Cuando se trata de generadores en las que necesita un poco de contexto, que a menudo utilizan la función de utilidad más adelante para dar una visión de ventana deslizante en un iterador:

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

Generará una vista de los elementos de la secuencia N en at Ie, cambiando de lugar de paso. p.ej.

>>> list(window([1,2,3,4,5],3)) 
[(1, 2, 3), (2, 3, 4), (3, 4, 5)] 

Cuando se utiliza en la búsqueda hacia delante/detrás situaciones en las que también tienen que lidiar con los números sin tener un valor siguiente o anterior, es posible que desee almohadilla de la secuencia con un valor apropiado, tal como Ninguno.

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

Inmediatamente anterior?

Te refieres a lo siguiente, ¿no?

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

Si desea n artículos anteriores, usted puede hacer esto con una especie de cola circular de tamaño 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
l=[1,2,3] 
for i,item in enumerate(l): 
    if item==2: 
     get_previous=l[i-1] 
     print get_previous 

>>>1 
5

Mira la utilidad de la lanzadera desde el Tempita project. Le da un objeto envoltorio alrededor del elemento de bucle que proporciona propiedades tales como anterior, siguiente, primero, último, etc.

Eche un vistazo a source code para la clase Looper, es bastante simple. Hay otros auxiliares de bucles como esos, pero no puedo recordar ningún otro en este momento.

Ejemplo:

> 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 
-2
No

muy Pythonic, pero se las trae y es simple:

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

que hacer: proteger los bordes

5

Sé que esto es viejo, pero ¿por qué no solo use 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 

Si ejecuta esto, verá que atrapa los elementos anteriores y siguientes, y no le importa repetir elementos en la lista.

+1

¿Por qué los votos a favor? Esto está bien y no implica bibliotecas externas ni funciones especiales. –

+0

La pregunta también solicitó el artículo anterior. ¿Y esto no funcionará incorrectamente si un artículo se repite? '[1,2,1,3]'? – Teepeemm

+0

@Teepeemm, sí, lo actualizaré con una versión que cumpla con los requisitos. – DuckPuncher

21

Una manera simple.

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

Lo usé, pero ampliado para evitar dejar caer los elementos de inicio/finalización: 'para prev, cur, next en zip ([Ninguno] + l [: - 1], l, l [1:] + [Ninguno]) : ' – Maximus

+0

@Maximus: Este comentario debería ser una respuesta. ¡Realmente genio! – Helio

0

Si desea que la solución para trabajar en iterables, la itertools' docs tiene una receta que hace exactamente lo que quiere:

import itertools 

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

Si está utilizando Python 2.x, utilice en lugar de itertools.izipzip

Cuestiones relacionadas