Dotychczasowe rozwiązania zajmowały się tylko listami, a większość z nich kopiuje listę. Z mojego doświadczenia wynika, że wiele razy nie jest to możliwe.
Nie zajmują się też tym, że na liście mogą znajdować się powtarzające się elementy.
Tytuł pytania brzmi „ Poprzednie i następne wartości wewnątrz pętli ”, ale jeśli większość odpowiedzi uruchomisz w pętli, w końcu ponownie przejdziesz przez całą listę dla każdego elementu, aby go znaleźć.
Więc właśnie stworzyłem funkcję, która. używając itertools
modułu, dzieli i dzieli iterowalne elementy oraz generuje krotki z poprzednimi i następnymi elementami razem. Nie do końca to, co robi twój kod, ale warto przyjrzeć się temu, ponieważ prawdopodobnie może rozwiązać twój problem.
from itertools import tee, islice, chain, izip
def previous_and_next(some_iterable):
prevs, items, nexts = tee(some_iterable, 3)
prevs = chain([None], prevs)
nexts = chain(islice(nexts, 1, None), [None])
return izip(prevs, items, nexts)
Następnie użyj go w pętli, a będziesz mieć w nim poprzednie i następne elementy:
mylist = ['banana', 'orange', 'apple', 'kiwi', 'tomato']
for previous, item, nxt in previous_and_next(mylist):
print "Item is now", item, "next is", nxt, "previous is", previous
Wyniki:
Item is now banana next is orange previous is None
Item is now orange next is apple previous is banana
Item is now apple next is kiwi previous is orange
Item is now kiwi next is tomato previous is apple
Item is now tomato next is None previous is kiwi
Będzie działać z każdą listą rozmiarów (ponieważ nie kopiuje listy) oraz z dowolnymi iterowalnymi (pliki, zestawy itp.). W ten sposób możesz po prostu iterować po sekwencji i mieć poprzednie i następne elementy dostępne w pętli. Nie ma potrzeby ponownego wyszukiwania pozycji w sekwencji.
Krótkie wyjaśnienie kodu:
tee
służy do wydajnego tworzenia 3 niezależnych iteratorów w sekwencji wejściowej
chain
łączy dwie sekwencje w jedną; jest tutaj używany do dołączania sekwencji jednoelementowej [None]
doprevs
islice
służy do tworzenia sekwencji wszystkich elementów z wyjątkiem pierwszego, a następnie chain
służy do dołączania None
na jego końcu a
- Istnieją teraz 3 niezależne sekwencje,
some_iterable
które wyglądają następująco:
prevs
: None, A, B, C, D, E
items
: A, B, C, D, E
nexts
: B, C, D, E, None
- ostatecznie
izip
służy do zamiany 3 sekwencji w jedną sekwencję trojaczków.
Zauważ, że izip
zatrzymuje się, gdy jakakolwiek sekwencja wejściowa zostanie wyczerpana, więc ostatni element prevs
zostanie zignorowany, co jest poprawne - nie ma takiego elementu, który byłby jego ostatnim elementem prev
. Moglibyśmy spróbować oderwać ostatnie elementy od, prevs
ale izip
zachowanie sprawia, że jest to zbędne
Należy również pamiętać, że tee
, izip
, islice
i chain
pochodzą z itertools
modułu; operują na swoich sekwencjach wejściowych w locie (leniwie), co czyni je wydajnymi i nie wprowadza konieczności posiadania w pamięci całej sekwencji na raz.
W python 3
programie pokaże błąd podczas importowania izip
, możesz użyć zip
zamiast izip
. Nie ma potrzeby importu zip
, predefiniowane jest w python 3
- źródło