14 ответов:
The
delсообщении удаляет элемент:del d[key]однако это изменяет существующий словарь, поэтому содержимое словаря изменяется для любого другого, у кого есть ссылка на тот же экземпляр. Возвратить новая словарь, сделайте копию словаря:
def removekey(d, key): r = dict(d) del r[key] return rThe
dict()конструктор делает мелкая копия. Чтобы сделать глубокую копию, см.copyмодуль.
обратите внимание, что создание копии для каждого диктатора
del/ назначение / etc. означает, что вы переходите от постоянного времени к линейному времени, а также используете линейное пространство. Для маленьких диктовок это не проблема. Но если вы планируете сделать много копий больших диктов, вы, вероятно, хотите другую структуру данных, например HAMT (как описано в ответ).
popмутирует словарь.>>>lol = {"hello":"gdbye"} >>>lol.pop("hello") 'gdbye' >>> lol {}Если вы хотите сохранить оригинал, вы можете просто скопировать его.
Я думаю, что ваше решение-лучший способ сделать это. Но если вы хотите другое решение, вы можете создать новый словарь с использованием ключей из старого словаря, не включая указанный ключ, например:
>>> a {0: 'zero', 1: 'one', 2: 'two', 3: 'three'} >>> {i:a[i] for i in a if i!=0} {1: 'one', 2: 'two', 3: 'three'}
The del заявление это то, что вы ищете. Если у вас есть словарь с именем foo с ключом "bar", вы можете удалить " bar " из foo следующим образом:
del foo['bar']обратите внимание, что это постоянно изменяет словарь работает. Если вы хотите сохранить исходный словарь, вам придется создать копию заранее:
>>> foo = {'bar': 'baz'} >>> fu = dict(foo) >>> del foo['bar'] >>> print foo {} >>> print fu {'bar': 'baz'}The
dictвызов делает мелкую копию. Если вы хотите глубокую копию, используйтеcopy.deepcopy.вот метод, который вы можете скопировать и вставить, для вашего удобства:
def minus_key(key, dictionary): shallow_copy = dict(dictionary) del shallow_copy[key] return shallow_copy
есть много хороших ответов, но я хочу подчеркнуть одну вещь.
можно использовать
dict.pop()метод и более универсальнаяdelсообщении для удаления элементов из словаря. Они оба мутируют исходный словарь, поэтому вам нужно сделать копию (см. подробности ниже).и оба они поднимут a
KeyErrorесли ключ, который вы предоставляете им, отсутствует в словарь:key_to_remove = "c" d = {"a": 1, "b": 2} del d[key_to_remove] # Raises `KeyError: 'c'`и
key_to_remove = "c" d = {"a": 1, "b": 2} d.pop(key_to_remove) # Raises `KeyError: 'c'`вы должны позаботиться об этом:
захватив исключение:
key_to_remove = "c" d = {"a": 1, "b": 2} try: del d[key_to_remove] except KeyError as ex: print("No such key: '%s'" % ex.message)и
key_to_remove = "c" d = {"a": 1, "b": 2} try: d.pop(key_to_remove) except KeyError as ex: print("No such key: '%s'" % ex.message)проведя проверку:
key_to_remove = "c" d = {"a": 1, "b": 2} if key_to_remove in d: del d[key_to_remove]и
key_to_remove = "c" d = {"a": 1, "b": 2} if key_to_remove in d: d.pop(key_to_remove)но с
pop()есть также гораздо более лаконичный способ-предоставить возвращаемое значение по умолчанию:key_to_remove = "c" d = {"a": 1, "b": 2} d.pop(key_to_remove, None) # No `KeyError` hereесли вы не используете
pop()чтобы получить значение удаляемого ключа, вы можете предоставить что угодно, не обязательноNone. Хотя это может быть, что с помощьюdelСinпроверка немного быстрее из-заpop()будучи функцией со своими собственными осложнениями, вызывающими накладные расходы. Обычно это не так, так чтоpop()со значением по умолчанию является достаточно хорошим.
что касается основного вопроса, вам нужно будет сделать копию вашего словаря, чтобы сохранить исходный словарь и иметь новый без ключа удаляется.
некоторые другие люди здесь предлагают сделать полную (глубокую) копию с
copy.deepcopy(), что может быть излишним," нормальная " (мелкая) копия, используяcopy.copy()илиdict.copy(), может быть достаточно. Словарь хранит ссылку на объект в качестве значения для ключа. Поэтому, когда вы удаляете ключ из словаря, эта ссылка удаляется, а не объект, на который ссылаются. Сам объект может быть удален позже автоматически сборщиком мусора, если нет других ссылок на него в памяти. Создание глубокой копии требует больше вычислений по сравнению с мелкой копией, поэтому она снижает производительность кода, делая копию, тратя память и предоставляя больше работы GC, иногда достаточно мелкой копии.однако, если у вас есть изменяемые объекты в качестве значений словаря и вы планируете изменить их позже в возвращенном словаре без ключа, вам нужно сделать глубокий копировать.
С мелкой копией:
def get_dict_wo_key(dictionary, key): """Returns a **shallow** copy of the dictionary without a key.""" _dict = dictionary.copy() _dict.pop(key, None) return _dict d = {"a": [1, 2, 3], "b": 2, "c": 3} key_to_remove = "c" new_d = get_dict_wo_key(d, key_to_remove) print(d) # {"a": [1, 2, 3], "b": 2, "c": 3} print(new_d) # {"a": [1, 2, 3], "b": 2} new_d["a"].append(100) print(d) # {"a": [1, 2, 3, 100], "b": 2, "c": 3} print(new_d) # {"a": [1, 2, 3, 100], "b": 2} new_d["b"] = 2222 print(d) # {"a": [1, 2, 3, 100], "b": 2, "c": 3} print(new_d) # {"a": [1, 2, 3, 100], "b": 2222}С глубоким копия:
from copy import deepcopy def get_dict_wo_key(dictionary, key): """Returns a **deep** copy of the dictionary without a key.""" _dict = deepcopy(dictionary) _dict.pop(key, None) return _dict d = {"a": [1, 2, 3], "b": 2, "c": 3} key_to_remove = "c" new_d = get_dict_wo_key(d, key_to_remove) print(d) # {"a": [1, 2, 3], "b": 2, "c": 3} print(new_d) # {"a": [1, 2, 3], "b": 2} new_d["a"].append(100) print(d) # {"a": [1, 2, 3], "b": 2, "c": 3} print(new_d) # {"a": [1, 2, 3, 100], "b": 2} new_d["b"] = 2222 print(d) # {"a": [1, 2, 3], "b": 2, "c": 3} print(new_d) # {"a": [1, 2, 3, 100], "b": 2222}
просто вызовите del d ['ключ'].
однако в производстве всегда рекомендуется проверять, существует ли "ключ"в d.
if 'key' in d: del d['key']
нет, нет другого пути, кроме
def dictMinus(dct, val): copy = dct.copy() del copy[val] return copyоднако часто создание копий только слегка измененных словарей, вероятно, не является хорошей идеей, потому что это приведет к сравнительно большим требованиям к памяти. Обычно лучше войти в старый словарь (если это даже необходимо), а затем изменить его.
>>> def delete_key(dict, key): ... del dict[key] ... return dict ... >>> test_dict = {'one': 1, 'two' : 2} >>> print delete_key(test_dict, 'two') {'one': 1} >>>это не делает никакой обработки ошибок, он предполагает, что ключ находится в dict, вы можете проверить, что первый и
raise, если не
... как я могу удалить элемент из словаря, чтобы вернуть копию (т. е., не изменяя оригинал)?
A
dict- это неправильная структура данных, чтобы использовать для этого.конечно, копирование dict и выскакивание из копии работает, а также создание нового dict с пониманием, но все это копирование требует времени-вы заменили операцию с постоянным временем на линейное время. И все эти живые копии сразу занимают пространство-линейное пространство в расчете копировать.
другие структуры данных, такие как хэш-массив сопоставляется нах, предназначены именно для такого варианта использования: добавление или удаление элемента возвращает копию в логарифмическом времени, разделяя большую часть своего хранения с оригиналом.1
конечно есть некоторые минусы. Производительность логарифмическая, а не постоянная (хотя с большой базой, как правило, 32-128). И, хотя вы можете сделать не мутирующий API идентичным к
dict," мутирующий " API, очевидно, отличается. И, самое главное, в комплекте с Python нет батарей HAMT.2The
pyrsistentбиблиотека-это довольно солидная реализация основанных на HAMT замен dict (и различных других типов) для Python. Он даже имеет изящный evolver API для переноса существующего мутирующего кода в постоянный код как можно более плавно. Но если вы хотите быть явным о возвращении копий, а не мутируя, вы просто используете его так:>>> from pyrsistent import m >>> d1 = m(a=1, b=2) >>> d2 = d1.set('c', 3) >>> d3 = d1.remove('a') >>> d1 pmap({'a': 1, 'b': 2}) >>> d2 pmap({'c': 3, 'a': 1, 'b': 2}) >>> d3 pmap({'b': 2})это
d3 = d1.remove('a')- это именно то, что спрашивается.если у вас есть изменяемые структуры данных, такие как
dictиlistвстроена вpmap, у вас все равно будут проблемы с псевдонимами-вы можете исправить это, только перейдя на неизменный путь вниз, встраиваяpmaps иpvectors.
1. HAMTs также стали популярными на таких языках, как Scala, Clojure, Haskell, потому что они играют очень хорошо с lock-free программирования и программного обеспечения транзакционной памяти, но ни один из них не является очень актуальным в Python.
2. На самом деле, там и HAMT в stdlib, используемый в реализации
contextvars. ранее отозванный PEP объясняет, почему. но это скрытая деталь реализации библиотеки, а не тип публичной коллекции.
здесь подход к дизайну верхнего уровня:
def eraseElement(d,k): if isinstance(d, dict): if k in d: d.pop(k) print(d) else: print("Cannot find matching key") else: print("Not able to delete") exp = {'A':34, 'B':55, 'C':87} eraseElement(exp, 'C')Я передаю словарь и ключ, который я хочу в свою функцию, проверяет, является ли это словарем, и если ключ в порядке, и если оба существуют, удаляет значение из словаря и распечатывает левые.
выход:
{'B': 55, 'A': 34}надеюсь, что это поможет!
хороший однострочный, чтобы проверить, присутствует ли ключ, удалить его, вернуть значение или по умолчанию:
ret_val = ('key' in body and body.pop('key')) or 5
ниже фрагмент кода поможет вам определенно, я добавил комментарии в каждой строке, которые помогут вам в понимании кода.
def execute(): dic = {'a':1,'b':2} dic2 = remove_key_from_dict(dic, 'b') print(dict2) # {'a': 1} print(dict) # {'a':1,'b':2} def remove_key_from_dict(dictionary_to_use, key_to_delete): copy_of_dict = dict(dictionary_to_use) # creating clone/copy of the dictionary if key_to_delete in copy_of_dict : # checking given key is present in the dictionary del copy_of_dict [key_to_delete] # deleting the key from the dictionary return copy_of_dict # returning the final dictionaryили вы также можете использовать dict.pop ()
d = {"a": 1, "b": 2} res = d.pop("c") # No `KeyError` here print (res) # this line will not executeили лучше
res = d.pop("c", "key not found") print (res) # key not found print (d) # {"a": 1, "b": 2} res = d.pop("b", "key not found") print (res) # 2 print (d) # {"a": 1}
вот еще один вариант использования понимания списка:
original_d = {'a': None, 'b': 'Some'} d = dict((k,v) for k, v in original_d.iteritems() if v) # result should be {'b': 'Some'}подход основан на ответе на этот пост: эффективный способ удалить ключи с пустыми строками из dict
Comments