Jak przeglądać wszystkie pozycje listy oprócz ostatniej?

160

Chciałbym przejrzeć listę, porównując każdą pozycję z następującą po niej.

Czy istnieje sposób, aby przejść przez wszystkie elementy oprócz ostatniego, używając funkcji for x in y? Wolałbym to zrobić bez korzystania z indeksów, jeśli mogę.

Uwaga

freespace odpowiedział na moje aktualne pytanie, dlatego przyjąłem odpowiedź, ale SilentGhost odpowiedział na pytanie, które powinienem był zadać.

Przepraszamy za zamieszanie.

David Sykes
źródło

Odpowiedzi:

316
for x in y[:-1]

Jeśli yjest generatorem, powyższe nie zadziała.

wolna przestrzeń
źródło
To odpowiada na moje pytanie, dziękuję, ale zapomniałem zapytać, jak dostanę przedmiot po x. czy to możliwe?
David Sykes
3
- 1 Nie sądzę, żeby to odpowiadało na pytanie. Nie porównuje każdego elementu z następnym. - odwl 0 sek.
Temu
4
Myślę, że zrobiłem. Autor powiedział, że chciałby zrobić X, a następnie zapytał, jak może zrobić Y. Odpowiedziałem, jak on może zrobić Y. To, że zaakceptował moją odpowiedź, oznaczałoby, że odpowiedziałem na zadane przez niego pytanie, jeśli nie na to, które naprawdę chciał zadać. Asker może zdegradować tę odpowiedź.
wolna przestrzeń
7
To, że PO powinien był zadać inne pytanie w pierwszym, nie oznacza, że ​​jego pytanie i ta odpowiedź nie są zbyt przydatne dla innych. +1
Prof. Falken
1
Wspomniałeś, że to nie działa w przypadku generatorów. Jaka jest alternatywa, kiedy yjest generator?
Joost
50

najłatwiejszy sposób porównania elementu sekwencji z następującymi:

for i, j in zip(a, a[1:]):
     # compare i (the current) to j (the following)
SilentGhost
źródło
15
To odpowiada na pytanie, które chciałbym zadać. Dzięki
David Sykes
3
Właściwie możesz pominąć pierwszy wycinek, ponieważ zip obcina dłuższą listę do długości krótszej. Pozwoli to zaoszczędzić ci jednego tworzenia listy. (Na wszelki wypadek masz do czynienia z ogromnymi listami. Ale w takim przypadku powinieneś postępować zgodnie z podejściem Antsa Aasmy, który niczego nie kopiuje.)
bayer
19

Jeśli chcesz uzyskać wszystkie elementy w parze sekwencji, użyj tego podejścia (funkcja parowania pochodzi z przykładów w module itertools).

from itertools import tee, izip, chain

def pairwise(seq):
    a,b = tee(seq)
    b.next()
    return izip(a,b)

for current_item, next_item in pairwise(y):
    if compare(current_item, next_item):
        # do what you have to do

Jeśli chcesz porównać ostatnią wartość z jakąś specjalną wartością, połącz tę wartość do końca

for current, next_item in pairwise(chain(y, [None])):
Ants Aasma
źródło
proszę zauważyć, że użycie next dla wbudowanych cieni nazw zmiennych
SilentGhost
1
Osobiście nie mam nic przeciwko cieniowaniu mniej używanych funkcji wbudowanych, gdy zakres zmiennej jest mały, a nazwa jest dobra dla czytelności. Niemniej jednak edytował nazwy zmiennych, aby zachować dobre praktyki kodowania.
Ants Aasma
5

jeśli chodziło Ci o porównanie n-tego elementu z n + 1-tym elementem na liście, z którym też możesz zrobić

>>> for i in range(len(list[:-1])):
...     print list[i]>list[i+1]

uwaga, nie ma tam żadnego twardego kodowania. To powinno być w porządku, chyba że czujesz inaczej.

Perpetualcoder
źródło
3
Możesz zamienić len (list [: - 1]) na len (list) - 1, aby uniknąć kopiowania listy. I unikaj używania zmiennej o nazwie list ...
Remy Blank
2

Aby porównać każdy element z następnym w iteratorze bez tworzenia wystąpienia listy:

import itertools
it = (x for x in range(10))
data1, data2 = itertools.tee(it)
data2.next()
for a, b in itertools.izip(data1, data2):
  print a, b
odwl
źródło
2
dokładnie to zasugerowało Ants Aasma stackoverflow.com/questions/914715/ ...
SilentGhost
1

Odpowiada to o co OP powinien był zapytać , tj. Przejść przez listę porównującą kolejne elementy (doskonała odpowiedź SilentGhost ), ale uogólnioną dla dowolnej grupy ( n-gram ): 2, 3, ... n:

zip(*(l[start:] for start in range(0, n)))

Przykłady:

l = range(0, 4)  # [0, 1, 2, 3]

list(zip(*(l[start:] for start in range(0, 2)))) # == [(0, 1), (1, 2), (2, 3)]
list(zip(*(l[start:] for start in range(0, 3)))) # == [(0, 1, 2), (1, 2, 3)]
list(zip(*(l[start:] for start in range(0, 4)))) # == [(0, 1, 2, 3)]
list(zip(*(l[start:] for start in range(0, 5)))) # == []

Objaśnienia:

  • l[start:] generuje listę / generator zaczynając od indeksu start
  • *listlub *generator: przekazuje wszystkie elementy do otaczającej funkcji, ziptak jakby została napisanazip(elem1, elem2, ...)

Uwaga:

AFAIK, ten kod jest tak leniwy, jak tylko może być. Nie testowany.

juanmirocks
źródło