2015-10-26 12 views
5

mam listę liczb całkowitych, które używam przez for pętli odkryć jeśli dwa elementy połączone są równe innej zmiennej t. Więc jeśli t był równy 10 i miałem listę intergers: l = [1,2,3,4,5,8,9], to funkcja powinna wydrukować wszystkie różne kombinacje liczb (1,9), (2,8).Dlaczego moja pętla for przeskakuje element na mojej liście?

czuję się prawie tam, ale coś dziwnego dzieje się z listy, gdy używam funkcji .pop(). Poniższy kod jest używany, aby pokazać wszystkie kombinacje liczb, które muszą być obliczane, ale co drugi element listy jest pomijany.

l = [1,2,5,8,13,15,26,38] 
c = 10 
for i in l: 
    first = i 
    l.pop(0) 
    for x in l: 
     second = x 
     print(first,second) 

Oto wynik:

1 2 
1 5 
1 8 
1 13 
1 15 
1 26 
1 38 
5 5 
5 8 
5 13 
5 15 
5 26 
5 38 
13 8 
13 13 
13 15 
13 26 
13 38 
26 13 
26 15 
26 26 
26 38 

Wskazówki jak 2, 8, 15 i 38 są pomijane. Używam l.pop, aby druga pętla for nie użyła pierwotnej wartości, a następna iteracja może następnie przejść do iteracji następnego elementu na liście.

+10

Z pewnością nie jestem ekspertem od Pythona, ale mogę powiedzieć, że w innych językach obiektowych ogólnie uważa się za całkiem zły pomysł, aby zmodyfikować albo iterator, albo kolekcję iterowaną z pętli. Moje pierwsze podejrzenie leżałoby tutaj. Wyskakujesz z listy, a następnie spróbuj wyświetlić listę odnośników [1] za kulisami ...ale lista [1] wynosi teraz 5, a nie 2, jak się spodziewasz, ponieważ zmieniłeś listę. –

+1

Myślę, że @DavidHoelzer dostał właściwą odpowiedź. –

+0

@AndrewRushton: To raczej sztuczne ograniczenie ... Możesz bezpiecznie usunąć elementy z listy, która jest aktualnie iterowana, jeśli powtarzasz je na liście, chociaż bezpieczniej jest iterować nad kopią listy. BTW '.pop (0)' jest raczej nieefektywna, ponieważ zmusza listę do przesunięcia wszystkich pozostałych elementów listy w dół, aby wypełnić lukę. –

Odpowiedz

9

Co próbujesz robić nie będzie działać, jak jesteś modyfikowanie listy podczas iteracji go. Powiedz, że bieżący "wskaźnik" wskazuje na pierwszy element. Teraz pop pierwsze, więc wskaźnik jest na drugim. Ale gdy pętla się przesunie, wskaźnik zostanie przesunięty do trzeciego, a drugi zostanie pominięty.

Wydaje chcesz znaleźć kombinacje z listy. Istnieje kilka innych sposobów, można spróbować:

  • najbliżej Twojej obecnego podejścia: Użyj while pętlę zamiast for pętli

    while l: 
        first = l.pop(0) 
        for second in l: 
         print(first, second) 
    
  • Albo może po prostu iteracyjne indeksy zamiast list sami:

    for i in range(len(l)): 
        for k in range(i+1, len(l)): 
         print(l[i], l[k]) 
    
  • Albo po prostu użyć itertools.combinations

    import itertools 
    for first, second in itertools.combinations(l, 2): 
        print(first, second) 
    

Jednak można zrobić lepiej. Ponieważ szukasz pary liczb, która dodaje się do pewnej liczby docelowej, po prostu odejmij pierwszą od celu, aby uzyskać drugą i sprawdź, czy ta druga liczba znajduje się na liście liczb. Użyj set aby ten odnośnika zdarzyć w stałym czasie, zmniejszając ogólną złożoność czasową z O (n²) do O (n).

numbers = set([1,2,5,8,13,15,26,38]) 
target = 10 
for first in numbers: 
    second = target - first 
    if second > first and second in numbers: 
     print(first, second) 
+0

Wielkie dzięki pomocy. Wszystko działa teraz –

0

Musisz wybrać inne podejście. Nie można usuwać elementów z listy podczas iteracji za pomocą pętli for.

Powiązane problemy