Czy istnieje sposób na usunięcie elementu ze słownika w Pythonie?
Dodatkowo, jak mogę usunąć element ze słownika, aby zwrócić kopię (tj. Nie modyfikując oryginału)?
python
dictionary
del
Richzilla
źródło
źródło
pop
metoda zmienia słownika w miejscu . Dlatego zmienia odniesienie do słownika, który został przekazany przez program wywołujący do „funkcji pomocnika”. Zatem „funkcja pomocnika” nie musi niczego zwracać, ponieważ oryginalne odwołanie do słownika w wywołującym zostanie już zmienione. Nie przypisuj zwrotu zdict.pop()
niczego, jeśli go nie potrzebujesz. EG:do stuff with my_dict; my_dict.pop(my_key, None); do more stuff with my_dict # now doesn't have my_key
. Użyj wdeepcopy(my_dict)
razie potrzeby.d.pop()
, poprawiłem tytuł, aby zadać pytanie określone w szczegółach.d.pop(key)
. Ale jeśli cokolwiek zmodyfikuje płytką kopię, masz dobrze znany problem z aliasingiem . Pomaga, jeśli powiesz nam szerszy kontekst. (Czy coś jeszcze zmienia wartości dykta? Czy próbujesz destrukcyjnie iterować listę? Jeśli nie, co?)Odpowiedzi:
del
Oświadczenie usuwa element:Powoduje to jednak mutację istniejącego słownika, więc zawartość słownika zmienia się dla każdego, kto ma odwołanie do tej samej instancji. Aby zwrócić nowy słownik, wykonaj jego kopię:
dict()
Konstruktor robi płytkie kopię . Aby wykonać głęboką kopię, zobaczcopy
moduł .Pamiętaj, że wykonanie kopii dla każdego nagrania
del
/ zadania / etc. oznacza, że przechodzisz od czasu stałego do czasu liniowego, a także używasz przestrzeni liniowej. W przypadku małych nagrań nie stanowi to problemu. Ale jeśli planujesz wykonać wiele kopii dużych nagrań, prawdopodobnie potrzebujesz innej struktury danych, na przykład HAMT (jak opisano w tej odpowiedzi ).źródło
dict
pętlę, pojawi się błąd:RuntimeError: dictionary changed size during iteration
pop
metodą, która w rzeczywistości robi to samo? Czy to nie jest bardziej pytoniczne? (jest to metoda dykta, a nie specjalne słowo zastrzeżone)?pop
mutuje słownik.Jeśli chcesz zachować oryginał, możesz go po prostu skopiować.
źródło
pop
zwraca wartość „pękniętą”, co pozwala na użycie tej wartości z dowolnego innego powodu. Jeśli nie jest to bardziej „Pythonic”, powiedziałbym, że wydaje się to lepsze na pewno :). To nie jest dyktando, ale działa tak samo dla obu: github.com/ivanlmj/python-prototypes/blob/master/3.4/…pop
można podać domyślną wartość, która zostanie zwrócona, gdy brakuje klucza w nagraniu. Dobrze jest, gdy trzeba usunąć kilka kluczy, ale niektórych z nich może brakować;del
rzuciłbyKeyError
w takim przypadku.Myślę, że twoje rozwiązanie jest najlepszym sposobem na to. Ale jeśli chcesz innego rozwiązania, możesz utworzyć nowy słownik przy użyciu kluczy ze starego słownika bez dołączania określonego klucza, na przykład:
źródło
{i:a[i] for i in a if i not in [0, 1, 2]}
jeśli chcesz usunąć kilka elementów.{k:v for k,v in a.items() if k != 0}
Myślę, że lepiej by było .**kwargs
,some_function(**{k:v for k,v in some_dict.items() if k not 'some_key'})
Instrukcja del jest tym, czego szukasz. Jeśli masz słownik o nazwie foo z kluczem o nazwie „bar”, możesz usunąć „bar” z foo w następujący sposób:
Zauważ, że to trwale modyfikuje obsługiwany słownik. Jeśli chcesz zachować oryginalny słownik, musisz wcześniej utworzyć kopię:
dict
Rozmowa sprawia płytką kopię. Jeśli chcesz głębokiej kopii, użyjcopy.deepcopy
.Oto metoda, którą możesz skopiować i wkleić dla Twojej wygody:
źródło
>>>
często jest używany w przykładach python? Tak, python-doc zawiera wiele takich rzeczy. Ale taki kod nie jest wygodny w przypadku kopiowania . Jestem zdezorientowany ...>>>
>>>
. Tak, jest w stylu REPL, ale porozmawiajmy szczerze: jedyny człowiek napisał tę próbkę, a 1000 ją przeczytało. Myślę, że dobrze byłoby pisać przykłady w sposób umożliwiający łatwe kopiowanie i uruchamianie. Nie lubię ręcznie usuwać kątowników. Lub kopiuj wiersz po wierszu .. Więc nie rozumiem: dlaczego te kąty wciąż tam są))) Być może coś nie wiem?Jest wiele fajnych odpowiedzi, ale chcę podkreślić jedną rzecz.
Możesz użyć zarówno
dict.pop()
metody, jak i bardziej ogólnejdel
instrukcji, aby usunąć elementy ze słownika. Obaj mutują oryginalny słownik, więc musisz zrobić kopię (zobacz szczegóły poniżej).I oba podniosą,
KeyError
jeśli klucz, który im podajesz, nie jest obecny w słowniku:i
Musisz się tym zająć:
przechwytując wyjątek:
i
poprzez sprawdzenie:
i
ale
pop()
jest też o wiele bardziej zwięzły sposób - podaj domyślną wartość zwracaną:O ile nie użyjesz go
pop()
do odzyskania wartości klucza, możesz podać wszystko, co nie jest konieczneNone
. Chociaż może się zdarzyć, że używaniedel
zin
kontrolą jest nieco szybsze, ponieważpop()
jest funkcją z własnymi komplikacjami powodującymi narzut. Zwykle tak nie jest, więcpop()
przy domyślnej wartości jest wystarczająco dobra.Jeśli chodzi o główne pytanie, będziesz musiał zrobić kopię swojego słownika, aby zapisać oryginalny słownik i mieć nowy bez wyjmowania klucza.
Niektórzy inni ludzie sugerują tutaj wykonanie pełnej (głębokiej) kopii
copy.deepcopy()
, która może być przesadą, „normalną” (płytką) kopią, używająccopy.copy()
lubdict.copy()
, może wystarczyć. Słownik przechowuje odwołanie do obiektu jako wartość klucza. Kiedy więc usuniesz klucz ze słownika, odwołanie to zostanie usunięte, a nie odwołany do obiektu. Sam obiekt może zostać później automatycznie usunięty przez moduł wyrzucający elementy bezużyteczne, jeśli nie ma w nim innych odniesień. Wykonywanie głębokiej kopii wymaga więcej obliczeń w porównaniu z płytką kopią, więc zmniejsza wydajność kodu, tworząc kopię, marnując pamięć i zapewniając więcej pracy GC, czasami płytka kopia wystarcza.Jeśli jednak masz zmienne obiekty jako wartości słownikowe i planujesz zmodyfikować je później w zwróconym słowniku bez klucza, musisz wykonać głęboką kopię.
Z płytką kopią:
Z głęboką kopią:
źródło
A
dict
jest złą strukturą danych do użycia w tym celu.Jasne, kopiowanie nagrania i wyskakiwanie z kopii działa, podobnie jak budowanie nowego nagrania ze zrozumieniem, ale całe to kopiowanie wymaga czasu - zastąpiłeś operację w czasie stałym operacją w czasie liniowym. Wszystkie żywe kopie jednocześnie zajmują miejsce - przestrzeń liniowa na kopię.
Inne struktury danych, takie jak próby mapowania tablicy skrótów , są zaprojektowane do tego rodzaju przypadków użycia: dodanie lub usunięcie elementu zwraca kopię w czasie logarytmicznym, dzieląc większość miejsca z oryginałem . 1
Oczywiście są pewne wady. Wydajność jest raczej logarytmiczna niż stała (chociaż z dużą bazą, zwykle 32-128). I chociaż można uczynić niezmutujący interfejs API identycznym z
dict
, „mutujący” interfejs API jest oczywiście inny. A przede wszystkim w Pythonie nie ma akumulatorów HAMT. 2)pyrsistent
Biblioteka jest całkiem solidne wdrożenie HAMT opartych DICT-zamienniki (i różnych innych typów) dla Pythona. Ma nawet niezły interfejs API do ewolucji do przenoszenia istniejącego kodu mutującego na trwały kod tak płynnie, jak to możliwe. Ale jeśli chcesz wyraźnie mówić o zwrocie kopii, a nie o mutacji, użyj jej w następujący sposób:Właśnie
d3 = d1.remove('a')
o to pyta pytanie.Jeśli masz zmienne struktury danych, takie jak
dict
ilist
osadzone w nichpmap
, nadal będziesz mieć problemy z aliasingiem - możesz to naprawić, przechodząc niezmiennie do końca, osadzającpmap
s ipvector
s.1. HAMT stały się również popularne w językach takich jak Scala, Clojure, Haskell, ponieważ grają bardzo ładnie dzięki programowaniu bez blokady i pamięci transakcyjnej oprogramowania, ale żaden z nich nie jest bardzo istotny w Pythonie.
2. W rzeczywistości jest stdlib HAMT, używany do implementacji
contextvars
. Wcześniej wycofany PEP wyjaśnia, dlaczego. Jest to jednak ukryty szczegół implementacji biblioteki, a nie typ kolekcji publicznej.źródło
Wynik:
d = {1: 2, '2': 3}
źródło
Wystarczy wywołać del d [„klucz”].
Jednak w produkcji zawsze dobrą praktyką jest sprawdzanie, czy „d” istnieje w d.
źródło
try-except
bloku. Przynajmniej będzie to operacja atomowa;)d.pop('key', None)
, to oneliner. Ale rzeczywiste pytanie dotyczyło uzyskania słownika bez jednego klucza, a nie modyfikacji słownika. Więc zrozumienie - to dobry wybór tutaj;)Nie, nie ma innego wyjścia niż
Jednak często tworzenie kopii tylko nieznacznie zmienionych słowników prawdopodobnie nie jest dobrym pomysłem, ponieważ spowoduje stosunkowo duże zapotrzebowanie na pamięć. Zwykle lepiej jest zalogować stary słownik (jeśli to konieczne), a następnie zmodyfikować go.
źródło
źródło
nie powoduje to żadnej obsługi błędów, zakłada, że klucz znajduje się w słowie, możesz najpierw to sprawdzić, a
raise
jeśli nieźródło
del test_dict[key]
?Oto podejście do projektowania na najwyższym poziomie:
Przekazuję słownik i klucz, który chcę, do mojej funkcji, sprawdza, czy jest to słownik i czy klucz jest w porządku, a jeśli oba istnieją, usuwa wartość ze słownika i drukuje resztki.
Wynik:
{'B': 55, 'A': 34}
Mam nadzieję, że to pomaga!
źródło
Poniższy fragment kodu zdecydowanie ci pomoże, dodałem komentarze w każdym wierszu, które pomogą ci w zrozumieniu kodu.
lub możesz także użyć dict.pop ()
lub lepsze jest podejście
źródło
Oto kolejna odmiana wykorzystująca rozumienie listy:
Podejście to opiera się na odpowiedzi z tego postu: Skuteczny sposób usuwania kluczy z pustych ciągów ze słownika
źródło
if v
byif k is not 'a'
odpowiedzieć na op. Ale nie sądzę, że jest to skuteczny sposób, ponieważ usuwa element w O (n) zamiast O (log n), tak jak pop lub del.Poniższy kod utworzy kopię nagrania
species
i usunie elementy, których nie matrans_HI
źródło