2012-01-20 6 views
17

Decir que tengo una lista:Ciclo a través de la lista a partir de un elemento determinado

l = [1, 2, 3, 4] 

Y quiero ciclo a través de él. Normalmente, sería hacer algo como esto,

1, 2, 3, 4, 1, 2, 3, 4, 1, 2... 

Quiero ser capaz de empezar en un determinado momento del ciclo, no necesariamente un índice, pero tal vez un elemento de juego. Decir que quería empezar en cualquier elemento de la lista ==4, la salida sería,

4, 1, 2, 3, 4, 1, 2, 3, 4, 1... 

¿Cómo puedo lograr esto?

Respuesta

20

Mira itertools módulo. Proporciona toda la funcionalidad necesaria.

from itertools import cycle, islice, dropwhile 

L = [1, 2, 3, 4] 

cycled = cycle(L) # cycle thorugh the list 'L' 
skipped = dropwhile(lambda x: x != 4, cycled) # drop the values until x==4 
sliced = islice(skipped, None, 10) # take the first 10 values 

result = list(sliced) # create a list from iterator 
print(result) 

Salida:

[4, 1, 2, 3, 4, 1, 2, 3, 4, 1] 
7

Utilice el operador aritmético mod. Supongamos que usted está comenzando desde la posición k, entonces k debe actualizarse como esto:

k = (k + 1) % len(l) 

Si quieres empezar a partir de un determinado elemento, no índice, siempre se puede mirar hacia arriba como k = l.index(x) donde se desea el x ít.

2
import itertools as it 
l = [1, 2, 3, 4] 
list(it.islice(it.dropwhile(lambda x: x != 4, it.cycle(l)), 10)) 
# returns: [4, 1, 2, 3, 4, 1, 2, 3, 4, 1] 

por lo que el iterador que quieres es:

it.dropwhile(lambda x: x != 4, it.cycle(l)) 
+4

'4 .__ cmp__' también trabaja igual que la fea lambda –

+0

@gnibbler que se necesitaría para poner' '4'entre paréntesis (4) .__ cmp__'. De lo contrario, no funciona (al menos en Python 2.7.2). Y con paréntesis, no se ve tan hermoso. – ovgolovin

+0

@gnibbler Y a partir de Python 3 se necesitaría usar '__eq__' en lugar de' __cmp__' (no hay '__cmp__' a partir de la versión 3). – ovgolovin

2

No soy un gran fan de la importación de módulos cuando se pueden hacer cosas por su cuenta en un par de líneas tales. Aquí está mi solución sin importaciones:

def cycle(my_list, start_at=None): 
    start_at = 0 if start_at is None else my_list.index(start_at) 
    while True: 
     yield my_list[start_at] 
     start_at = (start_at + 1) % len(my_list) 

Esto devolverá un iterador (infinito) looping su lista. Para obtener el siguiente elemento en el ciclo que debe utilizar la instrucción next:

>>> it1 = cycle([101,102,103,104]) 
>>> next(it1), next(it1), next(it1), next(it1), next(it1) 
(101, 102, 103, 104, 101) # and so on ... 
>>> it1 = cycle([101,102,103,104], start_at=103) 
>>> next(it1), next(it1), next(it1), next(it1), next(it1) 
(103, 104, 101, 102, 103) # and so on ... 
+4

'itertools' está escrito en' C'. Entonces, es bastante rápido aparte de su elocuencia. – ovgolovin

0

Otra opción es raro que el ciclismo a través de listas se puede lograr hacia atrás. Por ejemplo:

# Run this once 
myList = ['foo', 'bar', 'baz', 'boom'] 
myItem = 'baz' 

# Run this repeatedly to cycle through the list 
if myItem in myList: 
    myItem = myList[myList.index(myItem)-1] 
    print myItem 
Cuestiones relacionadas