2012-01-20 18 views
17

Powiedzmy mam listę:Przechodzić listy począwszy od pewnego elementu

l = [1, 2, 3, 4] 

I chcę, aby przejść przez niego. Normalnie byłoby zrobić coś takiego,

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

Chcę być w stanie rozpocząć w pewnym momencie cyklu, niekoniecznie indeksu, ale może dopasowanie elementu. Chciałem powiedzieć, aby uruchomić na dowolnym elementem listy ==4, to wyjście byłoby

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

W jaki sposób można to osiągnąć?

Odpowiedz

20

Spójrz na itertools moduł. Zapewnia wszystkie niezbędne funkcje.

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) 

wyjściowa:

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

Użyj operatora arytmetycznego mod. Załóżmy, że począwszy od pozycji k, następnie k powinny być aktualizowane tak:

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

Jeśli chcesz zacząć od pewnego elementu, a nie indeks, zawsze możesz to sprawdzić jak k = l.index(x) gdzie x jest pożądana pozycja.

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] 

więc iterator chcesz to:

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

'4 .__ cmp__' działa również zamiast brzydkiego lambda –

+0

@gnibbler zajęłoby umieścić' '4' w nawiasie (4) .__ cmp__'. W przeciwnym razie nie działa (przynajmniej w Pythonie 2.7.2). I z nawiasami nie wygląda tak pięknie. – ovgolovin

+0

@gnibbler A od Pythona 3 trzeba by użyć '__eq__' zamiast' __cmp__' (nie ma '__cmp__' od wersji 3). – ovgolovin

2

Nie jestem tak wielkim fanem importowania modułów, kiedy można robić rzeczy według własnych w kilku liniach. Oto moje rozwiązanie bez importowania:

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) 

Spowoduje to zwrócenie (nieskończonej) iteracji zapętlającej twoją listę. Aby uzyskać następnego elementu w cyklu należy użyć instrukcji 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' jest napisane w' C'. Jest więc dość szybki, niezależnie od jego elokwencji. – ovgolovin

0

Inną opcją dziwne jest to, że na rowerze przez list może być dokonany tyłu. Na przykład:

# 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 
Powiązane problemy