Chciałbym znać najlepszy sposób (bardziej zwarty i „pytoniczny”), aby wykonać specjalne traktowanie ostatniego elementu w pętli for. Istnieje fragment kodu, który powinien być wywoływany tylko między elementami, w ostatnim jest tłumiony.
Oto jak obecnie to robię:
for i, data in enumerate(data_list):
code_that_is_done_for_every_element
if i != len(data_list) - 1:
code_that_is_done_between_elements
Czy jest jakiś lepszy sposób?
Uwaga: nie chcę tego robić przy użyciu takich hacków, jak używanie reduce
.;)
Odpowiedzi:
W większości przypadków łatwiej (i taniej) jest zrobić pierwszą iterację specjalnym przypadkiem zamiast ostatniego:
Będzie to działać dla każdego iterowalnego, nawet dla tych, które nie mają
len()
:Poza tym nie sądzę, że istnieje ogólnie lepsze rozwiązanie, ponieważ zależy to od tego, co próbujesz zrobić. Na przykład, jeśli budujesz ciąg z listy, naturalnie lepiej jest użyć
str.join()
niżfor
pętli „ze specjalnym przypadkiem”.Stosując tę samą zasadę, ale bardziej kompaktową:
Wygląda znajomo, prawda? :)
W przypadku @ofko i innych, którzy naprawdę muszą dowiedzieć się, czy aktualna wartość iterowalności bez
len()
jest ostatnia, musisz spojrzeć w przyszłość:Następnie możesz użyć tego w następujący sposób:
źródło
if
której można by uniknąć, gdyby pętla została podzielona na dwie pętle. Jest to jednak istotne tylko przy iteracji ogromnej listy danych.next()
. Następnie wykorzystuję to, że iterator sam jest iterowalny, więc mogę go używać wfor
pętli do wyczerpania, iteracji od drugiej do ostatniej wartości. Podczas tego procesu zachowuję lokalnie wartość pobraną z iteratora lokalnie iyield
ostatnią zamiast tego. W ten sposób wiem, że będzie jeszcze jedna wartość. Po pętli for zgłosiłem każdą wartość oprócz ostatniej.Chociaż to pytanie jest dość stare, przyszedłem tutaj przez Google i znalazłem dość prosty sposób: cięcie list. Powiedzmy, że chcesz wstawić znak „&” między wszystkimi wpisami listy.
Zwraca „1 i 2 i 3”.
źródło
len(l)=1000000
w tym przykładzie program będzie działał przez chwilę.append
jest zalecane afaik.l=[1,2,3]; l.append(4);
„Kod między” jest przykładem wzoru głowa-ogon .
Masz przedmiot, po którym następuje sekwencja par (pomiędzy, przedmiot). Możesz także zobaczyć to jako sekwencję par (element, między), a następnie element. Zasadniczo łatwiej jest potraktować pierwszy element jako wyjątkowy, a wszystkie pozostałe jako „standardową” obudowę.
Ponadto, aby uniknąć powtarzania kodu, musisz podać funkcję lub inny obiekt zawierający kod, którego nie chcesz powtarzać. Osadzanie instrukcji if w pętli, która zawsze jest fałszywa, z wyjątkiem jednego razu, jest trochę głupie.
Jest to bardziej niezawodne, ponieważ nieco łatwiej jest udowodnić, że nie tworzy dodatkowej struktury danych (tj. Kopii listy) i nie wymaga dużo zmarnowanego wykonania warunku if , który zawsze jest fałszywy, z wyjątkiem jednego.
źródło
if
instrukcje, więc argument „zmarnowane wykonanie” nie ma zastosowania.if
s”. Oczywiście masz na myśli „czystość kodu”?if
instrukcji jest naprawdę uważane za czystsze przez społeczność Python?Jeśli chcesz po prostu zmodyfikować ostatni element
data_list
, możesz po prostu użyć notacji:Wygląda jednak na to, że robisz więcej. Nie ma nic złego na twojej drodze. Rzuciłem nawet okiem na kod Django dla ich znaczników szablonów i robią to, co robisz.
źródło
if data != datalist[-1]:
i utrzymanie tego samego wszystkiego byłoby moim zdaniem najlepszym sposobem na zakodowanie tego.jeśli przedmioty są unikalne:
inne opcje:
źródło
Jest to podobne do podejścia Ants Aasma, ale bez użycia modułu itertools. Jest to również opóźniony iterator, który wyprzedza pojedynczy element w strumieniu iteratora:
źródło
Możesz użyć przesuwanego okna nad danymi wejściowymi, aby uzyskać podgląd następnej wartości i użyć wartownika do wykrycia ostatniej wartości. Działa to na każdym iterowalnym, więc nie musisz wcześniej znać długości. Implementacja parami pochodzi z receptur itertools .
źródło
Czy nie ma możliwości iteracji nad wszystkim oprócz ostatniego elementu i potraktowania ostatniego poza pętlą? W końcu tworzona jest pętla, aby zrobić coś podobnego do wszystkich elementów, nad którymi zapętlasz; jeśli jeden element potrzebuje czegoś specjalnego, nie powinien znajdować się w pętli.
(patrz także to pytanie: czy ostatni element w pętli zasługuje na osobne traktowanie )
EDYCJA: ponieważ pytanie dotyczy bardziej „pomiędzy”, albo pierwszy element jest szczególny, ponieważ nie ma poprzednika, lub ostatni element jest wyjątkowy, ponieważ nie ma następcy.
źródło
Lubię podejście @ ethan-t, ale
while True
jest niebezpieczne z mojego punktu widzenia.Tutaj
data_list
jest tak, że ostatni element jest równy pod względem wartości do pierwszego z listy. L może być zamienione,data_list
ale w tym przypadku po pętli jest puste.while True
można również użyć, jeśli sprawdzisz, czy lista nie jest pusta przed przetwarzaniem lub sprawdzenie nie jest potrzebne (ouch!).Najlepsze jest to, że jest szybki. Złe - jest zniszczalne (
data_list
staje się puste).Najbardziej intuicyjne rozwiązanie:
O tak, już to zaproponowałeś!
źródło
Na twojej drodze nie ma nic złego, chyba że będziesz mieć 100 000 pętli i chcesz zaoszczędzić 100 000 instrukcji „jeśli”. W takim przypadku możesz przejść w ten sposób:
Wyjścia:
Ale tak naprawdę, w twoim przypadku wydaje mi się, że to przesada.
W każdym razie prawdopodobnie będziesz miał więcej szczęścia z krojeniem:
Lub tylko :
W końcu KISS to sposób na zrobienie czegoś, co działałoby z każdym iterowalnym, w tym bez
__len__
:Ouputs:
Jeśli wydaje mi się, że zrobiłbym to w ten sposób, wydaje mi się to proste.
źródło
item
zamiast go ponownie obliczać za pomocąlist[-1]
. Niemniej jednak: nie sądzę, aby o to prosił PO, prawda?iterable.__iter__()
- proszę nie wywoływać__
funkcji bezpośrednio. Powinno byćiter(iterable)
.Użyj krojenia i,
is
aby sprawdzić ostatni element:Zastrzeżenie emptor : Działa to tylko wtedy, gdy wszystkie elementy na liście są faktycznie różne (mają różne lokalizacje w pamięci). Pod maską Python może wykrywać równe elementy i ponownie wykorzystywać dla nich te same obiekty. Na przykład dla ciągów o tej samej wartości i wspólnych liczbach całkowitych.
źródło
jeśli przeglądasz listę, dla mnie to też działało:
źródło
Google przyniosło mi to stare pytanie i myślę, że mógłbym dodać inne podejście do tego problemu.
Większość odpowiedzi tutaj dotyczyłaby właściwego traktowania kontroli pętli for, tak jak ją poproszono, ale jeśli lista_danych jest możliwa do zniszczenia, sugerowałbym, żebyś wyskakiwał elementy z listy, aż skończy się pusta lista:
możesz nawet użyć while len (element_list), jeśli nie musisz nic robić z ostatnim elementem. Uważam to rozwiązanie za bardziej eleganckie niż radzenie sobie z next ().
źródło
Dla mnie najprostszym i pytonowym sposobem obsługi specjalnego przypadku na końcu listy jest:
Oczywiście można to również wykorzystać do specjalnego traktowania pierwszego elementu.
źródło
Zamiast liczyć, możesz także odliczać:
źródło
Opóźnij specjalną obsługę ostatniego elementu, aż do zakończenia pętli.
źródło
Może być wiele sposobów. krojenie będzie najszybsze. Dodanie jeszcze jednego, który używa metody .index ():
źródło
Przyjmując dane wejściowe jako iterator, oto sposób użycia tee i izip z itertools:
Próbny:
źródło
Najprostsze rozwiązanie, jakie przychodzi mi na myśl, to:
Dlatego zawsze patrzymy w przyszłość o jeden element, opóźniając przetwarzanie o jedną iterację. Aby pominąć robienie czegoś podczas pierwszej iteracji, po prostu wychwytuję błąd.
Oczywiście musisz się trochę zastanowić,
NameError
aby zostać podniesionym, kiedy chcesz.Zachowaj także `counstruct
Oznacza to, że nazwa new nie była wcześniej zdefiniowana. Jeśli jesteś paranoikiem, możesz upewnić się, że
new
nie istnieje, używając:Alternatywnie możesz oczywiście użyć instrukcji if (
if notfirst: print(new) else: notfirst = True
). Ale o ile wiem, koszty ogólne są większe.więc spodziewam się, że koszty ogólne nie będą możliwe do wybrania.
źródło
Policz elementy raz i nadążaj za liczbą pozostałych elementów:
W ten sposób oceniasz długość listy tylko raz. Wiele rozwiązań na tej stronie wydaje się zakładać, że długość jest niedostępna z góry, ale nie jest to częścią twojego pytania. Jeśli masz długość, użyj jej.
źródło
Jednym prostym rozwiązaniem, które przychodzi na myśl, byłoby:
Drugie równie proste rozwiązanie można uzyskać za pomocą licznika:
źródło