2012-01-24 16 views
72

wiem usunąć wpis, „klucza” z mojego słownika d, bezpiecznie zrobić:Usuwanie wielu klawiszy ze słownika bezpiecznie

if d.has_key('key'): 
    del d['key'] 

Jednak muszę usunąć wiele wpisów ze słownika bezpiecznie. Myślałem o zdefiniowaniu wpisów w krotce, ponieważ będę musiał to zrobić więcej niż raz.

entitiesToREmove = ('a', 'b', 'c') 
for x in entitiesToRemove: 
    if d.has_key(x): 
     del d[x] 

Jednak zastanawiałem się, czy istnieje mądrzejszy sposób, aby to zrobić?

+2

czas pobierania ze słownika jest prawie O (1) ze względu na krzyżowym kreskowaniem. Jeśli nie usuniesz znacznej części wpisów, nie sądzę, że zrobisz znacznie lepiej. – ncmathsadist

+1

Odpowiedź @mattbornskiego wydaje się bardziej kanoniczna, a także lektorska. –

+0

StackOverflow hath spoken: 'klucz in d' jest bardziej Pythoniczny niż' d.has_key (klucz) 'https://stackoverflow.com/questions/1323410/has-key-or-in –

Odpowiedz

30

Dlaczego nie podoba:

entries = ('a', 'b', 'c') 
the_dict = {'b': 'foo'} 

def entries_to_remove(entries, the_dict): 
    for key in entries: 
     if key in the_dict: 
      del the_dict[key] 

Bardziej zwarta wersja została dostarczona przez mattbornski wykorzystaniem dict.pop()

2

Dlaczego nie:

entriestoremove = (2,5,1) 
for e in entriestoremove: 
    if d.has_key(e): 
     del d[e] 

Nie wiem co masz na myśli przez "inteligentniejszy sposób". Z pewnością istnieją inne sposoby, może ze słownika listowe:

entriestoremove = (2,5,1) 
newdict = {x for x in d if x not in entriestoremove} 
136
d = {'some':'data'} 
entriesToRemove = ('any', 'iterable') 
for k in entriesToRemove: 
    d.pop(k, None) 
+11

** To. ** To jest sprytny wybór Pythonisty. 'dict.pop()' eliminuje potrzebę testowania istnienia klucza. _Excellent._ –

56

Korzystanie Dict Zrozumienia

final_dict = {key: t[key] for key in t if key not in [key1, key2]} 

gdzie key1 i key2 mają zostać usunięte.

W poniższym przykładzie klucze "b" i "c" mają zostać usunięte. & jest przechowywany na liście kluczy.

>>> a 
{'a': 1, 'c': 3, 'b': 2, 'd': 4} 
>>> keys = ["b", "c"] 
>>> print {key: a[key] for key in a if key not in keys} 
{'a': 1, 'd': 4} 
>>> 
+1

nowy słownik? rozumienie listy? Powinieneś dostosować odpowiedź do osoby zadającej pytanie;) – Glaslos

+0

tworzy nowy słownik, ale był to jeden liniowiec, więc o nim wspomniałem. –

+2

To rozwiązanie ma poważne działanie, gdy zmienna trzymająca ma dalsze zastosowanie w programie. Innymi słowy, dyktatura, z której usunięto klucze, jest znacznie wydajniejsza niż nowo utworzony dyktat z zachowanymi przedmiotami. – Apalala

15

Jeśli potrzebne również do pobierania wartości dla kluczy jesteś usuwania, byłoby to bardzo dobry sposób, aby to zrobić:

valuesRemoved = [d.pop(k, None) for k in entitiesToRemove] 

Można by oczywiście nadal robić to tylko dla usunięcie kluczy z d, ale niepotrzebnie tworzysz listę wartości ze zrozumieniem listy. Jest także trochę niejasne, aby używać rozumienia list tylko dla efektu ubocznego funkcji.

+2

Lub jeśli chcesz zachować usunięte wpisy * jako słownik: * 'valuesRemoved = dict ((k, d.pop (k, None)) dla k w entityToRemove)' i tak dalej. – kindall

+0

Możesz odrzucić przypisanie do zmiennej. W takim lub w takim przypadku jest to najkrótsze i najbardziej pythonic rozwiązanie, które powinno być oznaczone jako odpowiedź bezpośrednia IMHO. –

12

rozwiązaniem jest użycie map i filter funkcje

python 2

d={"a":1,"b":2,"c":3} 
l=("a","b","d") 
map(d.__delitem__, filter(d.__contains__,l)) 
print(d) 

python 3

d={"a":1,"b":2,"c":3} 
l=("a","b","d") 
list(map(d.__delitem__, filter(d.__contains__,l))) 
print(d) 

otrzymasz:

{'c': 3} 
+0

To nie działa dla mnie z pythonem 3.4: '>>> d = {" a ": 1," b ": 2," c ": 3} >>> l = (" a "," b "," d ") >>> mapa (d .__ delitem__, filtr (zm.__contains __, l)) >>> print (d) {'a': 1, 'b': 2, 'c': 3} ' – Risadinha

+0

@Risadinha' list (map (d .__ delitem __, filter (d .__ zawiera __, l))) '.... w pythonie 3.4 funkcja mapy zwraca iterator –

+2

lub' deque (map (...), maxlen = 0) 'aby uniknąć budowania listy None wartości; pierwszy import z 'from collections import deque' – Jason

3

nie mam problemu z żadnym z istniejących odpowiedzi, ale byłem zaskoczony, aby nie znaleźć tego rozwiązania:

keys_to_remove = ['a', 'b', 'c'] 
my_dict = {k: v for k, v in zip("a b c d e f g".split(' '), [0, 1, 2, 3, 4, 5, 6])} 

for k in keys_to_remove: 
    try: 
     del my_dict[k] 
    except KeyError: 
     pass 

assert my_dict == {'d': 3, 'e': 4, 'f': 5, 'g': 6} 

UWAGA: natknąłem to pytanie pochodzące z here. A moja odpowiedź jest związana z this answer.

1

rolki

import functools 

#: not key(c) in d 
d = {"a": "avalue", "b": "bvalue", "d": "dvalue"} 

entitiesToREmove = ('a', 'b', 'c') 

#: python2 
map(lambda x: functools.partial(d.pop, x, None)(), entitiesToREmove) 

#: python3 

list(map(lambda x: functools.partial(d.pop, x, None)(), entitiesToREmove)) 

print(d) 
# output: {'d': 'dvalue'}