@Ivo, żadne z tych stwierdzeń nie jest prawdziwe. Nigdy nie powinieneś modyfikować listy, której używasz podczas iteracji. for x in listJeśli używasz, while loopto jest w porządku. pokazana pętla usunie puste ciągi, dopóki nie będzie już pustych ciągów, a następnie zatrzyma się. Właściwie nawet nie spojrzałem na pytanie (tylko tytuł), ale odpowiedziałem dokładnie taką samą pętlą jak to możliwe! Jeśli nie chcesz używać wyrażeń ani filtrów ze względu na pamięć, jest to bardzo pytoniczne rozwiązanie.
aaronasterling
4
Nadal bardzo ważny punkt, aby nigdy nie zmieniać listy, nad którą się iterujesz :)
Eduard Luca
1
@EduardLuca, jeśli celem iteracji po liście jest jej zmiana, jest to odwrotność tego, co powinieneś zrobić. Musisz tylko uważać, aby nie spowodować nieoczekiwanego zachowania.
JFA
1
@EduardLuca, @JFA: Chodzi o to, że NIE iteruje po żadnej liście. Zrobiłby, gdyby napisał coś w formie for var in list:, ale tutaj napisał while const in list:. co nie jest niczym. po prostu powtarza ten sam kod, dopóki warunek nie zostanie spełniony.
Jeśli jesteś , że wciśnięty do wykonania, itertooljestifilter to nawet faster- >>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)2.3468542098999023; >>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)0.04442191123962402.
Humphrey Bogart
4
@cpburnz Very true. Jednak ifilterwyniki są oceniane leniwie, a nie za jednym razem - argumentowałbym, że w większości przypadków ifilterjest to lepsze. Ciekawe, że przy użyciu filterjest nadal szybszy niż owijania ifilterw listchociaż.
Humphrey Bogart,
3
Jeśli zrobisz to z listą liczb, zauważ, że zera również zostaną usunięte (uwaga: użyłem tylko pierwszych 3 metod), więc będziesz potrzebować alternatywnej metody.
SnoringFrog
2
Koncentruje się tylko na szybkości, a nie na pythonicznym rozwiązaniu (pytanie, które zostało zadane). Zrozumienie listy jest rozwiązaniem pythonowym, a filtru należy używać tylko wtedy, gdy profilowanie wykazało, że listcomp jest wąskim gardłem.
Tryt21
3
@ ktokolwiek-wspomina o-lub-sugeruje-Python-3, po prostu edytuj i zaktualizuj odpowiedź. Dyskutowaliśmy o Pythonie 2, kiedy zadano to pytanie, nawet Python 3 został wydany prawie 2 lata. Ale zaktualizuj zarówno wyniki Python 2, jak i 3.
Livivetter
237
Korzystanie ze zrozumienia listy jest najbardziej pythonicznym sposobem:
>>> strings =["first","","second"]>>>[x for x in strings if x]['first','second']
Jeśli lista musi zostać zmodyfikowana w miejscu, ponieważ istnieją inne odwołania, które muszą zobaczyć zaktualizowane dane, użyj przypisania wycinka:
Podoba mi się to rozwiązanie, ponieważ można je łatwo dostosować. Gdybym musiał usunąć nie tylko pustych strun, ale struny, które są po prostu białe znaki, np [x for x in strings if x.strip()].
Bond
67
filtr ma do tego specjalną opcję:
filter(None, sequence)
Odfiltruje wszystkie elementy, które mają wartość False. Nie ma potrzeby używania tutaj rzeczywistego urządzenia do wywoływania, takiego jak bool, len i tak dalej.
nie zadziała, jeśli między ciągiem słowa jest spacja. na przykład: [„witaj świecie”, „”, „witaj”, „”]. >> [„helloworld”, „”, „hello”, „”] Czy masz jakieś inne rozwiązanie, aby zachować spacje w obrębie elementu na liście, ale usuwać inne?
Reihan_amn
Zauważ, że filter(None, lstr)nie usuwa pustych ciągów ze spacją.' ' Tak, ponieważ to nie jest pusty ciąg.
AMC
15
Odpowiedź od @ Ib33X jest niesamowita. Jeśli chcesz usunąć każdy pusty ciąg, po usunięciu. musisz także użyć metody pasków. W przeciwnym razie zwróci również pusty ciąg, jeśli ma białe spacje. Podobnie „” będzie również ważne dla tej odpowiedzi. Można to osiągnąć przez.
strings =["first","","second "," "][x.strip()for x in strings if x.strip()]
Odpowiedź na to będzie ["first", "second"].
Jeśli filterzamiast tego chcesz użyć metody, możesz zrobić podobnie
list(filter(lambda item: item.strip(), strings)). To daje ten sam wynik.
Jeśli Twoje listy mają różne typy (z wyjątkiem Brak), możesz mieć większy problem.
Tryt21
Jakie typy? Próbowałem z int i innymi typami liczbowymi, łańcuchami, listami, tupami, setami i None i żadnych problemów. Widziałem, że jeśli istnieją jakieś typy zdefiniowane przez użytkownika, które nie obsługują metody str, mogą stanowić problem. Czy powinienem się martwić o coś innego?
thiruvenkadam
1
Jeśli masz str_list = [None, '', 0, "Hi", '', "Hello"], jest to znak źle zaprojektowanej aplikacji. Nie powinieneś mieć więcej niż jednego interfejsu (typu) i Brak na tej samej liście.
Tryt21,
3
Odzyskiwanie danych z bazy danych? lista argumentów funkcji podczas wykonywania testów automatycznych?
thiruvenkadam
3
Są to zwykle krotki.
Tryt21
7
W zależności od wielkości listy może być najbardziej wydajne, jeśli używasz list.remove () zamiast tworzyć nową listę:
l =["1","","3",""]whileTrue:try:
l.remove("")exceptValueError:break
Ma to tę zaletę, że nie tworzy nowej listy, ale ma tę wadę, że za każdym razem trzeba wyszukiwać od początku, chociaż w przeciwieństwie do korzystania z while '' in lpropozycji powyżej, wymaga ona wyszukiwania tylko raz dla każdego wystąpienia ''(z pewnością istnieje sposób, aby zachować najlepszą z obie metody, ale jest to bardziej skomplikowane).
jeśli chcesz zachować białe spacje w ciągu, możesz je przypadkowo usunąć za pomocą niektórych metod. Podobało ci się to podejście?
AMC
Dzięki stary, zadziałało to dla mnie z małą zmianą. tj.space_clean_list = [x.strip() for x in y if x.strip()]
Muhammad Mehran Khan Attari
6
Użyj filter:
newlist=filter(lambda x: len(x)>0, oldlist)
Wady używania filtra, jak wskazano, polegają na tym, że jest on wolniejszy niż alternatywy; jest również lambdazwykle kosztowne.
Lub możesz wybrać najprostszą i najbardziej iteracyjną ze wszystkich:
# I am assuming listtext is the original list containing (possibly) empty itemsfor item in listtext:if item:
newlist.append(str(item))# You can remove str() based on the content of your original list
jest to najbardziej intuicyjna metoda i robi to w przyzwoitym czasie.
Witamy w SO. Nie zostałeś zignorowany. Nie zostałeś zaatakowany przez anonimowego zstępującego. Otrzymałeś informację zwrotną. Wzmocnienie: Twój proponowany pierwszy argument dla filtra jest gorszy niż ten, lambda x: len(x)który jest gorszy niż lambda x : xto, które jest najgorsze z 4 rozwiązań w wybranej odpowiedzi. Preferowane jest prawidłowe funkcjonowanie, ale niewystarczające. Najedź kursorem na przycisk głosowania: mówi „Ta odpowiedź nie jest przydatna”.
John Machin
5
Jak donosi Aziz Altofilter(None, lstr) , nie usuwa pustych łańcuchów ze spacją, ' 'ale jeśli jesteś pewien, że lstr zawiera tylko łańcuch, którego możesz użyćfilter(str.strip, lstr)
s and s.strip()jest potrzebne, jeśli chcemy w pełni powielić filter(None, words)zaakceptowaną odpowiedź. Poprawiłem powyżej przykładowe funkcje x2 i upuściłem x2 złe.
ankostis
-2
Aby uzyskać listę z kombinacją spacji i pustych wartości, użyj prostego zrozumienia listy -
>>> s =['I','am','a','','great',' ','',' ','person','!!','Do','you','think','its','a','','a','','joke','',' ','','?','','','','?']
Widzisz więc, ta lista zawiera kombinację spacji i elementów zerowych. Korzystanie z fragmentu -
>>> d =[x for x in s if x.strip()]>>> d
>>> d =['I','am','a','great','person','!!','Do','you','think','its','a','a','joke','?','?']
for x in list
Jeśli używasz,while loop
to jest w porządku. pokazana pętla usunie puste ciągi, dopóki nie będzie już pustych ciągów, a następnie zatrzyma się. Właściwie nawet nie spojrzałem na pytanie (tylko tytuł), ale odpowiedziałem dokładnie taką samą pętlą jak to możliwe! Jeśli nie chcesz używać wyrażeń ani filtrów ze względu na pamięć, jest to bardzo pytoniczne rozwiązanie.for var in list:
, ale tutaj napisałwhile const in list:
. co nie jest niczym. po prostu powtarza ten sam kod, dopóki warunek nie zostanie spełniony.Odpowiedzi:
Użyłbym
filter
:Python 3 zwraca iterator
filter
, dlatego powinien być zawarty w wywołaniu dolist()
źródło
itertool
jestifilter
to nawet faster->>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)
2.3468542098999023
;>>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)
0.04442191123962402
.ifilter
wyniki są oceniane leniwie, a nie za jednym razem - argumentowałbym, że w większości przypadkówifilter
jest to lepsze. Ciekawe, że przy użyciufilter
jest nadal szybszy niż owijaniaifilter
wlist
chociaż.Korzystanie ze zrozumienia listy jest najbardziej pythonicznym sposobem:
Jeśli lista musi zostać zmodyfikowana w miejscu, ponieważ istnieją inne odwołania, które muszą zobaczyć zaktualizowane dane, użyj przypisania wycinka:
źródło
[x for x in strings if x.strip()]
.filtr ma do tego specjalną opcję:
Odfiltruje wszystkie elementy, które mają wartość False. Nie ma potrzeby używania tutaj rzeczywistego urządzenia do wywoływania, takiego jak bool, len i tak dalej.
Jest równie szybki jak mapa (bool, ...)
źródło
Porównaj czas
Zauważ, że
filter(None, lstr)
nie usuwa pustych ciągów ze spacją' '
, tylko przycina się''
podczas' '.join(lstr).split()
usuwania obu.Aby użyć
filter()
z usuniętymi ciągami białych znaków, zajmuje to dużo więcej czasu:źródło
filter(None, lstr)
nie usuwa pustych ciągów ze spacją.' '
Tak, ponieważ to nie jest pusty ciąg.Odpowiedź od @ Ib33X jest niesamowita. Jeśli chcesz usunąć każdy pusty ciąg, po usunięciu. musisz także użyć metody pasków. W przeciwnym razie zwróci również pusty ciąg, jeśli ma białe spacje. Podobnie „” będzie również ważne dla tej odpowiedzi. Można to osiągnąć przez.
Odpowiedź na to będzie
["first", "second"]
.Jeśli
filter
zamiast tego chcesz użyć metody, możesz zrobić podobnielist(filter(lambda item: item.strip(), strings))
. To daje ten sam wynik.źródło
Zamiast if x użyłbym if X! = '', Aby po prostu wyeliminować puste ciągi. Lubię to:
Pozwoli to zachować typ danych Brak na liście. Ponadto, jeśli twoja lista zawiera liczby całkowite, a 0 jest jedną z nich, również zostanie zachowana.
Na przykład,
źródło
str_list = [None, '', 0, "Hi", '', "Hello"]
, jest to znak źle zaprojektowanej aplikacji. Nie powinieneś mieć więcej niż jednego interfejsu (typu) i Brak na tej samej liście.W zależności od wielkości listy może być najbardziej wydajne, jeśli używasz list.remove () zamiast tworzyć nową listę:
Ma to tę zaletę, że nie tworzy nowej listy, ale ma tę wadę, że za każdym razem trzeba wyszukiwać od początku, chociaż w przeciwieństwie do korzystania z
while '' in l
propozycji powyżej, wymaga ona wyszukiwania tylko raz dla każdego wystąpienia''
(z pewnością istnieje sposób, aby zachować najlepszą z obie metody, ale jest to bardziej skomplikowane).źródło
ary[:] = [e for e in ary if e]
. Znacznie czystszy i nie używa wyjątków dla przepływu sterowania.Pamiętaj, że jeśli chcesz zachować białe spacje w ciągu , możesz je przypadkowo usunąć za pomocą niektórych metod. Jeśli masz tę listę
[„witaj świecie”, „”, „”, „witaj”] czego możesz chcieć [„witaj świecie”, „witaj”]
najpierw przytnij listę, aby przekonwertować dowolny biały znak na pusty ciąg znaków:
następnie usuń pusty ciąg z listy
źródło
space_clean_list = [x.strip() for x in y if x.strip()]
Użyj
filter
:Wady używania filtra, jak wskazano, polegają na tym, że jest on wolniejszy niż alternatywy; jest również
lambda
zwykle kosztowne.Lub możesz wybrać najprostszą i najbardziej iteracyjną ze wszystkich:
jest to najbardziej intuicyjna metoda i robi to w przyzwoitym czasie.
źródło
lambda x: len(x)
który jest gorszy niżlambda x : x
to, które jest najgorsze z 4 rozwiązań w wybranej odpowiedzi. Preferowane jest prawidłowe funkcjonowanie, ale niewystarczające. Najedź kursorem na przycisk głosowania: mówi „Ta odpowiedź nie jest przydatna”.Jak donosi Aziz Alto
filter(None, lstr)
, nie usuwa pustych łańcuchów ze spacją,' '
ale jeśli jesteś pewien, że lstr zawiera tylko łańcuch, którego możesz użyćfilter(str.strip, lstr)
Porównaj czas na moim komputerze
Pozostaje najszybsze rozwiązanie do usuwania
''
i opróżniania łańcuchów ze spacją .' '
' '.join(lstr).split()
Jak podano w komentarzu, sytuacja wygląda inaczej, jeśli ciągi znaków zawierają spacje.
Możesz zobaczyć, że
filter(str.strip, lstr)
zachowaj ciągi ze spacjami, ale' '.join(lstr).split()
podzieli to ciągi.źródło
join
rozwiązanie podzieli ciągi znaków spacją, ale filtr nie. Dziękuję za komentarz Poprawiłem swoją odpowiedź.Podsumuj najlepsze odpowiedzi:
1. Wyeliminuj opróżnienia BEZ usuwania:
Oznacza to, że zachowane są ciągi znaków spacji:
PRO:
2. Aby wyeliminować opróżnienia po rozebraniu ...
2.a ... gdy ciągi NIE zawierają spacji między słowami:
PRO:
2.b ... kiedy ciągi znaków zawierają spacje między wyrazami?
PRO:
Testy porównawcze na maszynie 2018:
źródło
s and s.strip()
można uprościć do justs.strip()
.s and s.strip()
jest potrzebne, jeśli chcemy w pełni powielićfilter(None, words)
zaakceptowaną odpowiedź. Poprawiłem powyżej przykładowe funkcje x2 i upuściłem x2 złe.Aby uzyskać listę z kombinacją spacji i pustych wartości, użyj prostego zrozumienia listy -
Widzisz więc, ta lista zawiera kombinację spacji i elementów zerowych. Korzystanie z fragmentu -
źródło