1) Prawie angielski styl:
Sprawdź obecność za pomocą in
operatora, a następnie zastosuj remove
metodę.
if thing in some_list: some_list.remove(thing)
remove
Metoda usunie tylko pierwsze wystąpienie thing
, w celu usunięcia wszystkich wystąpień można użyć while
zamiast if
.
while thing in some_list: some_list.remove(thing)
- Dość proste, prawdopodobnie mój wybór. Dla małych list (nie mogę się oprzeć jednowarstwowym)
Ta postawa „najpierw strzelaj, zadawaj pytania, ostatnia” jest powszechna w Pythonie. Zamiast wcześniej przetestować, czy obiekt jest odpowiedni, po prostu wykonaj operację i wychwyć odpowiednie wyjątki:
try:
some_list.remove(thing)
except ValueError:
pass # or scream: thing not in some_list!
except AttributeError:
call_security("some_list not quacking like a list!")
Oczywiście druga klauzula z wyjątkiem powyższego przykładu ma nie tylko wątpliwy humor, ale jest całkowicie niepotrzebna (chodziło o zilustrowanie pisania kaczką osobom, które nie znają tego pojęcia).
Jeśli oczekujesz wielu wystąpień rzeczy:
while True:
try:
some_list.remove(thing)
except ValueError:
break
- trochę verbose dla tego konkretnego przypadku użycia, ale bardzo idiomatyczny w Pythonie.
- to działa lepiej niż # 1
- PEP 463 zaproponował krótszą składnię dla try / oprócz prostego użycia, które byłoby przydatne tutaj, ale nie został zatwierdzony.
Jednak za pomocą menedżera kontekstu suppress () kontekstowego (wprowadzonego w Pythonie 3.4) powyższy kod można uprościć do tego:
with suppress(ValueError, AttributeError):
some_list.remove(thing)
Ponownie, jeśli oczekujesz wielu wystąpień rzeczy:
with suppress(ValueError):
while True:
some_list.remove(thing)
3) Styl funkcjonalny:
Około 1993, Python got lambda
, reduce()
, filter()
i map()
, dzięki uprzejmości Lisp hakerów, którzy je pominąć i złożone łaty roboczych *. Możesz użyć filter
do usunięcia elementów z listy:
is_not_thing = lambda x: x is not thing
cleaned_list = filter(is_not_thing, some_list)
Istnieje skrót, który może być przydatny w twoim przypadku: jeśli chcesz odfiltrować puste elementy (w rzeczywistości elementy, w których bool(item) == False
np. None
Zero, puste ciągi znaków lub inne puste kolekcje), możesz przekazać None jako pierwszy argument:
cleaned_list = filter(None, some_list)
- [aktualizacja] : w Pythonie 2.x,
filter(function, iterable)
był równoważny [item for item in iterable if function(item)]
(lub [item for item in iterable if item]
jeśli pierwszy argument jest None
); w Pythonie 3.x jest teraz równoważne z (item for item in iterable if function(item))
. Subtelna różnica polega na tym, że filtr użyty do zwrócenia listy, teraz działa jak wyrażenie generatora - jest to OK, jeśli iterujesz tylko po oczyszczonej liście i odrzucasz ją, ale jeśli naprawdę potrzebujesz listy, musisz dołączyć filter()
wywołanie z list()
konstruktorem.
- * Te konstrukcje o smaku Lispy są w Pythonie uważane za trochę obcych. Około 2005 roku Guido mówił nawet o upuszczeniu
filter
- wraz z towarzyszami map
i reduce
(jeszcze ich nie ma, ale reduce
został przeniesiony do modułu funools , który warto sprawdzić, jeśli lubisz funkcje wyższego rzędu ).
4) Styl matematyczny:
Rozumienie list stało się preferowanym stylem do manipulowania listami w Pythonie od czasu wprowadzenia go w wersji 2.0 przez PEP 202 . Uzasadnieniem jest to, że Ułatwienia Lista zapewnić bardziej zwięzły sposób tworzenia list w sytuacjach, w których map()
i filter()
będzie stosowane obecnie i / lub zagnieżdżone pętle.
cleaned_list = [ x for x in some_list if x is not thing ]
Wyrażenia generatora zostały wprowadzone w wersji 2.4 przez PEP 289 . Wyrażenie generatora jest lepsze w sytuacjach, w których tak naprawdę nie potrzebujesz (lub nie chcesz) mieć pełnej listy utworzonej w pamięci - na przykład gdy chcesz po prostu iterować elementy pojedynczo. Jeśli iterujesz tylko po liście, możesz pomyśleć o wyrażeniu generatora jako leniwym zrozumieniu listy:
for item in (x for x in some_list if x is not thing):
do_your_thing_with(item)
Notatki
- możesz
!=
zamiast tego użyć operatora nierówności is not
( różnica jest ważna )
- dla krytyków metod sugerujących kopię listy: wbrew powszechnemu przekonaniu, wyrażenia generatora nie zawsze są bardziej wydajne niż listy - prosimy o profil przed złożeniem skargi
Zauważ, że spowoduje to usunięcie tylko jednego wystąpienia pustego ciągu z listy (tak jak zrobiłby to Twój kod). Czy twoja lista może zawierać więcej niż jeden?
źródło
Jeśli
index
nie znajdzie szukanego ciągu, rzuca to,ValueError
co widzisz. Albo złap ValueError:lub użyj
find
, która zwraca -1 w tym przypadku.źródło
>>> s [u'Hello', u'Cool', u'Glam'] >>> i = s.find("") Traceback (most recent call last): File "<pyshell#42>", line 1, in <module> i = s.find("") AttributeError: 'list' object has no attribute 'find'
remove()
jest znacznie bardziej bezpośrednie: bezpośrednio pokazuje, co ma zrobić kod (w rzeczywistości nie jest potrzebny indeks pośrednii
).Dodanie tej odpowiedzi jest kompletne, ale można ją wykorzystać tylko pod pewnymi warunkami.
Jeśli masz bardzo duże listy, usunięcie z końca listy pozwala uniknąć konieczności stosowania wewnętrznych elementów CPython
memmove
w sytuacjach, w których możesz ponownie zamówić listę. Daje to wzrost wydajności do usunięcia z końca listy, ponieważ nie będzie musiałmemmove
każdego elementu po tym, który usuwasz - cofnij się o krok (1) .W przypadku jednorazowego usunięcia różnica w wydajności może być do zaakceptowania, ale jeśli masz dużą listę i musisz usunąć wiele elementów - prawdopodobnie zauważysz spadek wydajności.
Chociaż wprawdzie w takich przypadkach przeszukiwanie pełnej listy może być również wąskim gardłem wydajności, chyba że elementy znajdują się głównie na początku listy.
Metodę tę można wykorzystać do wydajniejszego usuwania,
o ile dopuszczalne jest ponowne uporządkowanie listy. (2)
Możesz uniknąć błędu, gdy
item
nie ma go na liście.set
, zwłaszcza jeśli lista nie jest przeznaczona do przechowywania duplikatów.W praktyce może być jednak konieczne przechowywanie zmiennych danych, których nie można dodać do pliku
set
. Sprawdź także na btree, czy dane można zamówić.źródło
Eek, nie rób nic tak skomplikowanego:)
Tylko
filter()
twoje tagi.bool()
zwracaFalse
puste ciągi, więc zamiastpowinieneś napisać
lub jeszcze lepiej, umieść tę logikę w środku,
striplist()
aby nie zwracała pustych ciągów.źródło
striplist
funkcja, jak włączyć twoje rozwiązanie: def striplist (l): "" "usuwa białe spacje z ciągów znaków na liście l" "" return ([x.strip () dla x w l])[x.strip() for x in l if x.strip()]
albo użyć Python wbudowanejmap
ifilter
funkcje tak:filter(bool, map(str.strip, l))
. Jeśli chcesz przetestować go, oceniać to w interaktywnym tłumacza:filter(bool, map(str.strip, [' a', 'b ', ' c ', '', ' ']))
.None
zamiastbool
pierwszego argumentu.Oto inne podejście liniowe:
Nie tworzy kopii listy, nie wykonuje wielu przejść przez listę, nie wymaga dodatkowej obsługi wyjątków i zwraca dopasowany obiekt lub Brak, jeśli nie ma dopasowania. Jedynym problemem jest to, że jest to długa wypowiedź.
Ogólnie rzecz biorąc, gdy szukasz rozwiązania jednowierszowego, które nie zgłasza wyjątków, najlepszym rozwiązaniem jest next (), ponieważ jest to jedna z niewielu funkcji Pythona, która obsługuje domyślny argument.
źródło
Wszystko, co musisz zrobić, to to
ale ta metoda ma problem. Musisz umieścić coś w innym miejscu, więc znalazłem to:
źródło