Удалить элемент из словаря

Есть ли способ удалить элемент из словаря в Python?

Кроме того, как я могу удалить элемент из словаря, чтобы вернуть копию (то есть, не изменяя оригинал)?

+1201
источник поделиться
15 ответов

Оператор del удаляет элемент:

del d[key]

Однако это изменяет существующий словарь, поэтому содержимое словаря изменяется для всех, кто имеет ссылку на тот же экземпляр. Чтобы вернуть новый словарь, сделайте копию словаря:

def removekey(d, key):
    r = dict(d)
    del r[key]
    return r

Конструктор dict() делает поверхностную копию. Чтобы сделать глубокую копию, см. Модуль copy.


Обратите внимание, что создание копии для каждого dict del/assignment/etc. означает, что вы переходите от постоянного времени к линейному времени, а также используете линейное пространство. Для маленьких диктовок это не проблема. Но если вы планируете делать много копий больших диктовок, вам, вероятно, понадобится другая структура данных, например HAMT (как описано в этом ответе).

+1536
источник

pop мутирует словарь.

 >>>lol = {"hello":"gdbye"}
 >>>lol.pop("hello")
    'gdbye'
 >>> lol
     {}

Если вы хотите сохранить оригинал, вы можете просто скопировать его.

+209
источник
другие ответы

Связанные вопросы


Похожие вопросы

Я думаю, что ваше решение - лучший способ сделать это. Но если вы хотите другое решение, вы можете создать новый словарь с использованием ключей из старого словаря без указания вашего указанного ключа, например:

>>> 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'}
+70
источник

del statement - это то, что вы ищете. Если у вас есть словарь с именем foo с ключом, называемым "bar", вы можете удалить "bar" из foo следующим образом:

del foo['bar']

Обратите внимание, что это постоянно изменяет словарь, в котором работает. Если вы хотите сохранить исходный словарь, вам нужно будет создать копию заранее:

>>> foo = {'bar': 'baz'}
>>> fu = dict(foo)
>>> del foo['bar']
>>> print foo
{}
>>> print fu
{'bar': 'baz'}

dict вызывает мелкую копию. Если вы хотите получить глубокую копию, используйте copy.deepcopy.

Здесь вы можете скопировать и вставить для удобства:

def minus_key(key, dictionary):
    shallow_copy = dict(dictionary)
    del shallow_copy[key]
    return shallow_copy
+52
источник

Есть много хороших ответов, но я хочу подчеркнуть одну вещь.

Вы можете использовать как dict.pop() и более общий оператор del для удаления элементов из словаря. Они оба видоизменяют оригинальный словарь, поэтому вам нужно сделать копию (см. Подробности ниже).

И оба они 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() может быть достаточно, Словарь содержит ссылку на объект в качестве значения для ключа. Поэтому, когда вы удаляете ключ из словаря, эта ссылка удаляется, а не объект, на который ссылаются. Сам объект может быть впоследствии удален сборщиком мусора автоматически, если в памяти нет других ссылок на него. Создание глубокой копии требует больше вычислений по сравнению с мелкой копией, поэтому она снижает производительность кода, делая копию, тратя память и предоставляя больше работы ГХ, иногда достаточно мелкой копии.

Однако, если у вас есть изменяемые объекты в качестве значений словаря и вы планируете изменить их позже в возвращаемом словаре без ключа, вы должны сделать глубокую копию.

С мелкой копией:

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}
+47
источник
d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d

Результат: d = {1: 2, '2': 3}

+19
источник

… Как я могу удалить элемент из словаря, чтобы вернуть копию (то есть, не изменяя оригинал)?

dict - неправильная структура данных, используемая для этого.

Конечно, копирование dict и извлечение из копий работает, как и создание нового dict с пониманием, но все это копирование требует времени - вы заменили операцию с постоянным временем на операцию с линейным временем. И все эти живые копии сразу занимают место - линейное пространство за копию.

Другие структуры данных, такие как попытки сопоставления хеш-массива, предназначены именно для этого варианта использования: добавление или удаление элемента возвращает копию в логарифмическом времени, разделяя большую часть его хранилища с оригиналом. 1

Конечно, есть некоторые недостатки. Производительность скорее логарифмическая, чем постоянная (хотя с большим основанием, обычно 32-128). И хотя вы можете сделать API-интерфейс без мутаций идентичным dict, API-интерфейс с dict, очевидно, отличается. И, что самое главное, в Python нет батарей HAMT. 2

Библиотека pyrsistent является довольно надежной реализацией основанных на HAMT dict-замен (и других типов) для Python. У него даже есть отличный 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, у вас все равно будут проблемы с наложением pmap - вы можете исправить это, только pmap неизменным весь путь, pmap и pvector s.


1. HAMT также стали популярными в таких языках, как Scala, Clojure, Haskell, потому что они очень хорошо работают с программированием без блокировок и программной транзакционной памятью, но ни один из них не очень актуален в Python.

2. На самом деле в stdlib есть HAMT, используемый при реализации contextvars.Ранее отозванный ПКП объясняет почему.Но это скрытая деталь реализации библиотеки, а не публичный тип коллекции.

+15
источник

Просто позвоните del d ['key'].

Однако в производстве всегда полезно проверить, существует ли "ключ" в d.

if 'key' in d:
    del d['key']
+14
источник

Нет, нет другого пути, кроме

def dictMinus(dct, val):
   copy = dct.copy()
   del copy[val]
   return copy

Однако часто создание копий только слегка измененных словарей, вероятно, не очень хорошая идея, потому что это приведет к сравнительно большим потребностям в памяти. Обычно лучше записывать старый словарь (если это необходимо), а затем изменять его.

+7
источник
# mutate/remove with a default
ret_val = body.pop('key', 5)
# no mutation with a default
ret_val = body.get('key', 5)
+7
источник
>>> 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, если его не

+5
источник

Здесь используется подход верхнего уровня:

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}

Надеюсь, что это поможет!

+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}
+3
источник

Здесь другая вариация, использующая понимание списка:

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

+2
источник
    species = {'HI': {'1': (1215.671, 0.41600000000000004),
  '10': (919.351, 0.0012),
  '1025': (1025.722, 0.0791),
  '11': (918.129, 0.0009199999999999999),
  '12': (917.181, 0.000723),
  '1215': (1215.671, 0.41600000000000004),
  '13': (916.429, 0.0005769999999999999),
  '14': (915.824, 0.000468),
  '15': (915.329, 0.00038500000000000003),
 'CII': {'1036': (1036.3367, 0.11900000000000001), '1334': (1334.532, 0.129)}}

Следующий код создаст копию dict species и удалит элементы, которых нет в trans_HI

trans_HI=['1025','1215']
for transition in species['HI'].copy().keys():
    if transition not in trans_HI:
        species['HI'].pop(transition)
0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос