2009-10-28 5 views
40
l = range(100)       
for i in l:       
    print i,       
    print l.pop(0),     
    print l.pop(0) 

Powyższy kod Pythona nadaje wynikowi zupełnie inny od oczekiwanego. Chcę zapętlić elementy, aby można było pominąć element podczas pętli.Modyfikowanie listy podczas iteracji

Proszę wyjaśnić.

+12

Nie ma sposobu, aby powiedzieć, co masz nadzieję osiągnąć, patrząc na swój kod. –

+8

"różni się od oczekiwanego". Naprawdę? Czego oczekiwałeś? –

Odpowiedz

31

Zostałem ugryziony wcześniej przez (kogoś innego) "sprytny" kod, który próbuje zmodyfikować listę podczas iteracji nad nim. Postanowiłem, że nigdy nie zrobię tego w żadnych okolicznościach.

Możesz użyć operatora plasterka mylist[::3], aby przejść do co trzeciego elementu na liście.

mylist = [i for i in range(100)] 
for i in mylist[::3]: 
    print(i), 

Inne punkty o moim przykładzie odnoszą się do nowej składni w python 3.0.

  • używam listowych zdefiniować MyList ponieważ działa w Pythonie 3.0 (patrz niżej)
  • wydruku jest funkcją w python 3,0

Python 3.0 Zakres() teraz zachowuje się jak xrange() używane do zachowania się, z wyjątkiem tego, że działa z wartościami dowolnego rozmiaru. Ta ostatnia już nie istnieje.

+12

Jeśli obiekt listy jest wymagany, 'list (zakres (100))' jest szybszy i prostszy niż ta bezsensowna lista. Ponadto 'dla i w zakresie (100) [:: 3]:' działa. – Lenna

+3

Ponadto, jeśli chcesz po prostu powtórzyć liczby całkowite, lepiej używać "zakresu (0, 100, 3)" lub nawet "xrange (0, 100, 3)" (ten ostatni nie tworzy pełnej listy w ram). –

+0

@ Lenna, co powiesz na [zasięg (100)]? – wsysuper

10

Ogólna zasada polega na tym, że nie modyfikuje się kolekcji/tablicy/listy podczas iteracji.

Użyj listy pomocniczej, aby zapisać elementy, które chcesz wykonać, i wykonać tę logikę w pętli po pierwszej pętli.

8

Spróbuj tego. Pozwala uniknąć mutowania rzeczy, przez którą przechodzisz, co zwykle jest zapachem kodu.

for i in xrange(0, 100, 3): 
    print i 

Zobacz xrange.

+4

Python 3.0 range() teraz zachowuje się jak xrange(), aby zachowywać się, z wyjątkiem tego, że działa z wartościami dowolnego rozmiaru. Ta ostatnia już nie istnieje. –

46

wolno zmieniać pojemnik jesteś na pętli, bo iteratory w kontenerze nie będą informowane o swoich zmian i, jak zauważyłeś, to całkiem prawdopodobne, aby produkować zupełnie inną pętlę i/lub niepoprawny. W normalnych przypadkach pomocne jest zapętlenie kopii pojemnika, ale w twoim przypadku jest oczywiste, że nie musisz tego robić, ponieważ pojemnik będzie pusty po 50 odnogach pętli, a jeśli spróbujesz ponownie wystrzelić, " Otrzymam wyjątek.

Cokolwiek jest JEDNAK Czy jasne jest, jakie zachowanie próbujesz osiągnąć, jeśli w ogóle ?! Może potrafisz wyrazić swoje pragnienia za pomocą while ...?

i = 0 
while i < len(some_list): 
    print i,       
    print some_list.pop(0),     
    print some_list.pop(0) 
+1

Czekaj, czy inkrementujesz w pętli? – Snowman

+2

@maq, które nie jest konieczne. 'pop' faktycznie usuwa element. Tak więc wciąż patrzysz na element '0' i pojawiasz go. Działa zgodnie z przeznaczeniem. – ashes999

+0

Alex, stwierdziłem, że działa to na banalnych przykładach, czy powinniśmy tego unikać? na przykład >>> L = lista ('abcdefab') >>> do i w l: \t jeśli l.count (I)> 1: \t l.remove (I) –

0

Ta składnia slice tworzy kopię listy i robi to, co chcesz:

l = range(100) 
for i in l[:]: 
    print i, 
    print l.pop(0), 
    print l.pop(0) 
+3

Widzę to bardzo późno, ale ta odpowiedź jest błędna. Dostarczony kod ulegnie awarii po przejrzeniu ponad 50 elementów, ponieważ usuwa za każdym razem dwa elementy z oryginalnej listy, ale nie pomija żadnego z nich w plasterkach. – Blckknght

1

myślę, że to jest to, co chcesz:

l = range(100) 
index = 0      
for i in l:       
    print i,    
    try: 
     print l.pop(index+1),     
     print l.pop(index+1) 
    except: 
     pass 
    index += 1 

Jest bardzo przydatny do kodu kiedy liczba przedmiotów do puknięcia jest decyzją czasu pracy. Ale działa z bardzo złym skutkiem, a kod jest trudny do utrzymania.

7

Użyj pętli while, która sprawdza prawdziwości tablicy:

while array: 
    value = array.pop(0) 
    # do some calculation here 

I powinien to zrobić bez żadnych błędów lub śmieszne zachowanie.

+3

Upewnij się, że zawsze pukniesz co najmniej raz w każdą pętlę. –