Czy można jednocześnie usunąć wiele elementów z listy? Jeśli chcę usunąć elementy o indeksie 0 i 2 i spróbować czegoś takiego jak del somelist[0]
, a następnie del somelist[2]
, druga instrukcja faktycznie usunie somelist[3]
.
Przypuszczam, że zawsze mógłbym najpierw usunąć elementy o wyższym numerze, ale mam nadzieję, że jest lepszy sposób.
somelist = [ lst[i] for i in xrange(len(lst)) if i not in set(indices) ]
:?Z jakiegoś powodu nie podoba mi się żadna z odpowiedzi tutaj. Tak, działają, ale ściśle mówiąc, większość z nich nie usuwa elementów z listy, prawda? (Ale wykonanie kopii, a następnie zastąpienie oryginału kopią edytowaną).
Dlaczego po prostu nie usunąć najpierw wyższego indeksu?
Czy jest tego powód? Po prostu zrobiłbym:
Jeśli naprawdę nie chcesz usuwać elementów do tyłu, myślę, że powinieneś po prostu odliczyć wartości indeksów, które są większe niż ostatnio usunięty indeks (nie możesz naprawdę użyć tego samego indeksu, ponieważ masz inną listę) lub użyć kopię listy (co nie byłoby „usuwaniem”, ale zastąpieniem oryginału edytowaną kopią).
Czy czegoś tu brakuje, czy jest jakiś powód, aby NIE usuwać w odwrotnej kolejności?
źródło
Jeśli usuwasz wiele nieprzylegających elementów, to, co opisujesz, jest najlepszym sposobem (i tak, pamiętaj, aby zacząć od najwyższego indeksu).
Jeśli elementy sąsiadują ze sobą, możesz użyć składni przypisywania plasterków:
źródło
del a[2:10]
z tym samym efektem.Możesz użyć
numpy.delete
w następujący sposób:Jeśli nie masz nic przeciwko kończeniu na
numpy
tablicy na końcu, możesz pominąć rozszerzenie.tolist()
. Powinieneś także zobaczyć całkiem duże ulepszenia szybkości, dzięki czemu jest to bardziej skalowalne rozwiązanie. Nie testowałem tego, alenumpy
operacje są skompilowanym kodem napisanym w języku C lub Fortran.źródło
Jako specjalizacja odpowiedzi Grega możesz nawet użyć rozszerzonej składni plasterków. na przykład. Jeśli chcesz usunąć pozycje 0 i 2:
Oczywiście nie obejmuje to żadnego arbitralnego wyboru, ale z pewnością może działać w przypadku usunięcia dowolnych dwóch elementów.
źródło
Jako funkcja:
Działa w czasie n log (n) , co powinno uczynić z tego najszybszego poprawnego rozwiązania.
źródło
n log n
? Naprawdę? Myślę, że niedel list[index]
jest O (1).Więc zasadniczo chcesz usunąć wiele elementów za jednym przejściem? W takim przypadku pozycja następnego elementu do usunięcia zostanie przesunięta o tyle, ile usunięto wcześniej.
Naszym celem jest usunięcie wszystkich samogłosek, które są wstępnie obliczane jako indeksy 1, 4 i 7. Zauważ, że ważne jest, aby indeksy to_delete były w porządku rosnącym, w przeciwnym razie nie zadziała.
Byłoby bardziej skomplikowane, gdybyś chciał usunąć elementy w dowolnej kolejności. IMO, sortowanie
to_delete
może być łatwiejsze niż ustalenie, kiedy należy lub nie należy odejmowaćindex
.źródło
Jestem całkowitym początkującym w Pythonie, a moje programowanie w tej chwili jest co najmniej prymitywne i brudne, ale moim rozwiązaniem było użycie kombinacji podstawowych poleceń, których nauczyłem się we wczesnych samouczkach:
Oczywiście ze względu na konieczność wybrania znaku „znak do usunięcia” ma to swoje ograniczenia.
Jeśli chodzi o wydajność, jak skaluje się rozmiar listy, jestem pewien, że moje rozwiązanie jest nieoptymalne. Jest to jednak proste, co mam nadzieję, że przemówi do innych początkujących i będzie działać w prostych przypadkach, w których
some_list
ma dobrze znany format, np. Zawsze numeryczny ...źródło
Oto alternatywa, która nie używa enumerate () do tworzenia krotek (tak jak w oryginalnej odpowiedzi SilentGhost).
Wydaje mi się to bardziej czytelne. (Może czułbym się inaczej, gdybym miał w zwyczaju wyliczać). PRZESTROGA: Nie testowałem wydajności tych dwóch podejść.
UWAGA: składnia Pythona 2.7. W przypadku Pythona 3
xrange
=>range
.Stosowanie:
lista:
--- BONUS ---
Usuń wiele wartości z listy. Oznacza to, że mamy wartości, które chcemy usunąć:
Stosowanie:
lista:
To ta sama odpowiedź co poprzednio, ale tym razem dostarczyliśmy WARTOŚCI do usunięcia
[0, 44, 55]
.źródło
[ value for (i, value) in enumerate(lst) if i not in set(indices) ]
. Ale zostawię tutaj swoją odpowiedź, ponieważ pokazuję również, jak usuwać według wartości. Co jest prostszym przypadkiem, ale może komuś pomóc.indices_as_set = set(indices)
,[ value for (i, value) in enumerate(lst) if i not in indices_as_set ]
, aby ją przyspieszyć.delete__by_values()
?Alternatywna metoda rozumienia listy, która używa wartości indeksu list:
To zwraca:
źródło
index
jest mylące, ponieważ w liście zastosowano iteratorindex()
oto kolejna metoda, która usuwa elementy na miejscu. jeśli twoja lista jest naprawdę długa, jest szybsza.
źródło
Wspomniano o tym, ale jakoś nikt nie zdołał tego zrobić dobrze.
Na
O(n)
rozwiązanie byłoby:Jest to bardzo zbliżone do wersji SilentGhost , ale dodaje dwa nawiasy klamrowe.
źródło
O(n)
dzieje się tak, jeśli policzysz wyszukiwanialog(len(indices))
dla każdej iteracji.j not in indices
jestO(1)
.j not in indices
nadal wymaga wyszukiwania, czyliO(log(len(indices)))
. Chociaż zgadzam się, że wyszukiwanie w zestawie 2-elementowym kwalifikuje się takO(1)
, jak w ogólnym przypadku tak będzieO(log(N))
. Tak czy inaczejO(N log(N))
nadal bijeO(N^2)
.j not in indices
jestO(1)
, poważnie.Zasadniczo jest to to samo, co odpowiedź najczęściej głosowana, tylko inny sposób jej zapisania. Zwróć uwagę, że użycie l.index () nie jest dobrym pomysłem, ponieważ nie obsługuje ona zduplikowanych elementów na liście.
źródło
Metoda Remove spowoduje spore przesunięcia elementów listy. Myślę, że lepiej zrobić kopię:
źródło
technicznie odpowiedź brzmi NIE, nie można usunąć dwóch obiektów JEDNOCZEŚNIE. Jednak jest możliwe usunięcie dwóch obiektów w jednym wierszu pięknego Pythona.
usunie
foo['bar']
wówczas ponowniefoo['baz']
źródło
możemy to zrobić używając pętli for iterującej po indeksach po posortowaniu listy indeksów w porządku malejącym
źródło
Dla indeksów 0 i 2 z listy A:
Dla niektórych losowych indeksów do usunięcia z listy A:
źródło
Chciałem znaleźć sposób na porównanie różnych rozwiązań, które ułatwiają kręcenie gałkami.
Najpierw wygenerowałem moje dane:
Następnie zdefiniowałem swoje funkcje:
Następnie
timeit
porównywałem rozwiązania:Wynik
Wygrał więc generator z indeksami w a
set
. Idel
jest nieznacznie szybszypop
.źródło
Możesz użyć tej logiki:
źródło
Kolejna realizacja pomysłu usunięcia z najwyższego indeksu.
źródło
Właściwie mogę wymyślić dwa sposoby, aby to zrobić:
pokrój listę w taki sposób (spowoduje to usunięcie pierwszego, trzeciego i ósmego elementu)
somelist = somelist [1: 2] + somelist [3: 7] + somelist [8:]
zrób to na miejscu, ale pojedynczo:
somelist.pop (2) somelist.pop (0)
źródło
Możesz to zrobić na dyktandzie, a nie na liście. Na liście elementy są w kolejności. W dyktandzie zależą tylko od indeksu.
Prosty kod, aby to wyjaśnić, wykonując :
Sposób „konwersji” listy w dyktandzie to:
Odwrotność to:
W każdym razie myślę, że lepiej jest rozpocząć usuwanie z wyższego indeksu, jak powiedziałeś.
źródło
Aby uogólnić komentarz z @sth . Usuwanie pozycji w dowolnej klasie, która implementuje abc.MutableSequence ,
list
aw szczególności, odbywa się za pomocą__delitem__
metody magic. Ta metoda działa podobnie__getitem__
, co oznacza, że może akceptować liczbę całkowitą lub wycinek. Oto przykład:To wyjdzie
źródło
Importowanie go tylko z tego powodu może być przesadą, ale jeśli i tak używasz
pandas
, rozwiązanie jest proste i proste:źródło
Pozwala uniknąć kosztów sortowania i jawnego kopiowania listy.
źródło
A co z jednym z nich (jestem bardzo nowy w Pythonie, ale wydają się w porządku):
[„Atlantyk”, „Pacyfik”, „Indie”]
[„Atlantyk”, „Pacyfik”, „Indie”]
źródło
Żadna z odpowiedzi udzielonych do tej pory nie powoduje usunięcia w miejscu O (n) na długości listy dla dowolnej liczby indeksów do usunięcia, więc oto moja wersja:
źródło
Możesz też użyć usuwania.
źródło
Umieściłem to razem w
list_diff
funkcji, która po prostu przyjmuje dwie listy jako dane wejściowe i zwraca ich różnicę, zachowując oryginalną kolejność pierwszej listy.Przykładowe użycie:
źródło