Есть ли способ удалить элемент из словаря в Python?
Кроме того, как я могу удалить элемент из словаря, чтобы вернуть копию (то есть, не изменяя оригинал)?
python
dictionary
del
richzilla
источник
источник
pop
метод изменяет словарь на месте . Поэтому он изменяет ссылку на словарь, который был передан от вызывающей стороны к «вспомогательной функции». Таким образом, «вспомогательная функция» не должна ничего возвращать, так как исходная ссылка на словарь в вызывающей программе уже будет изменена. Не назначайте возвратdict.pop()
ни к чему, если он вам не нужен. EG:do stuff with my_dict; my_dict.pop(my_key, None); do more stuff with my_dict # now doesn't have my_key
. Используйтеdeepcopy(my_dict)
при необходимости.d.pop()
, я исправил название, чтобы задать вопрос, указанный в деталях.d.pop(key)
. Но если что-либо изменяет мелкую копию, у вас есть хорошо известная проблема с алиасами . Это поможет, если вы сообщите нам более широкий контекст. (Изменяет ли что-нибудь еще значения dict? Вы пытаетесь деструктивно перебирать список? Если нет, то что?)Ответы:
del
Оператор удаляет элемент:Однако это изменяет существующий словарь, поэтому содержимое словаря изменяется для всех, кто имеет ссылку на тот же экземпляр. Чтобы вернуть новый словарь, сделайте копию словаря:
dict()
Конструктор делает неполную копию . Чтобы сделать глубокую копию, см.copy
Модуль .Обратите внимание, что создание копии для каждого диктанта
del
/ назначения / и т. Д. означает, что вы переходите от постоянного времени к линейному времени, а также используете линейное пространство. Для маленьких диктовок это не проблема. Но если вы планируете делать много копий больших диктовок, вам, вероятно, понадобится другая структура данных, например HAMT (как описано в этом ответе ).источник
dict
цикл во время его прохождения, он выдаст ошибку:RuntimeError: dictionary changed size during iteration
pop
метода, который на самом деле делает то же самое? Разве это не более питонично? (будучи методом dict, а не специальным зарезервированным словом)?pop
мутирует словарь.Если вы хотите сохранить оригинал, вы можете просто скопировать его.
источник
pop
возвращает значение, которое было «вытолкнуто», что позволяет вам использовать это значение по любой другой причине. Если это не более "Pythonic", я бы сказал, что, кажется, лучше :). Это не диктат, но он работает одинаково для обоих: github.com/ivanlmj/python-prototypes/blob/master/3.4/…pop
может быть предоставлено значение по умолчанию, которое будет возвращено, если ключ отсутствует в dict. Хорошо, когда вам нужно удалить несколько ключей, но некоторые из них могут отсутствовать;del
бросил быKeyError
в таком случае.Я думаю, что ваше решение - лучший способ сделать это. Но если вам нужно другое решение, вы можете создать новый словарь, используя ключи из старого словаря, не включая указанный вами ключ, например так:
источник
{i:a[i] for i in a if i not in [0, 1, 2]}
если вы хотите удалить несколько элементов.{k:v for k,v in a.items() if k != 0}
Я думаю, лучше было бы .**kwargs
,some_function(**{k:v for k,v in some_dict.items() if k not 'some_key'})
Оператор del - это то, что вы ищете. Если у вас есть словарь с именем foo с ключом «bar», вы можете удалить «bar» из foo следующим образом:
Обратите внимание, что это постоянно изменяет используемый словарь. Если вы хотите сохранить исходный словарь, вам придется создать копию заранее:
dict
Вызов делает неполную копию. Если вы хотите глубокую копию, используйтеcopy.deepcopy
.Вот метод, который вы можете скопировать и вставить для вашего удобства:
источник
>>>
часто используется в python-примерах? Да, Python-Doc содержит много таких вещей. Но такой код неудобен для копирования . Я в замешательстве ...>>>
на python,>>>
. Да, это стиль REPL, но давайте поговорим откровенно: только один человек написал этот образец, и 1000 читали это. Я думаю, было бы здорово написать примеры так, чтобы можно было легко копировать и запускать. Я не люблю снимать эти угловые скобки вручную. Или копировать построчно .. Так что я не понимаю: почему эти углы все еще существуют))) Может быть, я чего-то не знаю?Есть много хороших ответов, но я хочу подчеркнуть одну вещь.
Вы можете использовать как
dict.pop()
метод, так и более общийdel
оператор для удаления элементов из словаря. Они оба видоизменяют оригинальный словарь, поэтому вам нужно сделать копию (см. Подробности ниже).И они оба выдают a,
KeyError
если ключ, который вы им предоставляете, отсутствует в словаре:а также
Вы должны позаботиться об этом:
захватывая исключение:
а также
выполнив проверку:
а также
но
pop()
есть и более краткий способ - укажите возвращаемое значение по умолчанию:Если вы не используете
pop()
для получения значения удаляемого ключа, вы можете предоставить все, что не нужноNone
. Хотя может случиться так, что использованиеdel
сin
проверкой немного быстрее из-за того,pop()
что это функция со своими собственными сложностями, вызывающими накладные расходы. Обычно это не так, поэтомуpop()
значение по умолчанию вполне достаточно.Что касается основного вопроса, вам нужно будет сделать копию своего словаря, чтобы сохранить исходный словарь и получить новый без удаления ключа.
Некоторые другие люди здесь предлагают сделать полную (глубокую) копию с
copy.deepcopy()
, что может быть избыточным, «нормальной» (мелкой) копией, с использованиемcopy.copy()
илиdict.copy()
может быть достаточно. Словарь хранит ссылку на объект в качестве значения для ключа. Поэтому, когда вы удаляете ключ из словаря, эта ссылка удаляется, а не объект, на который ссылаются. Сам объект может быть впоследствии удален сборщиком мусора автоматически, если в памяти нет других ссылок на него. Создание глубокой копии требует больше вычислений по сравнению с мелкой копией, поэтому она снижает производительность кода, делая копию, тратя память и предоставляя больше работы ГХ, иногда достаточно мелкой копии.Однако, если у вас есть изменяемые объекты в качестве значений словаря и вы планируете изменить их позже в возвращаемом словаре без ключа, вы должны сделать глубокую копию.
С мелкой копией:
С глубокой копией:
источник
A
dict
неправильная структура данных, чтобы использовать для этого.Конечно, копирование dict и извлечение из копий работает, как и создание нового dict с пониманием, но все это копирование требует времени - вы заменили операцию с постоянным временем на операцию с линейным временем. И все эти живые копии сразу занимают место - линейное пространство за копию.
Другие структуры данных, такие как попытки сопоставления хеш-массива , предназначены именно для этого варианта использования: добавление или удаление элемента возвращает копию в логарифмическом времени, разделяя большую часть его хранилища с оригиналом . 1
Конечно, есть некоторые недостатки. Производительность скорее логарифмическая, чем постоянная (хотя с большим основанием, обычно 32-128). И, хотя вы можете сделать API-интерфейс без мутаций идентичным, API-интерфейс с
dict
мутациями, очевидно, отличается. И, самое главное, в Python нет батарей HAMT. 2pyrsistent
Библиотека представляет собой довольно твердый реализация HAMT на основе Dict-заменителей (и различных других типов) для Python. У него даже есть отличный API для эволюции, позволяющий как можно более плавно портировать существующий изменяющийся код в постоянный код. Но если вы хотите быть откровенным о возврате копий, а не о мутировании, просто используйте его так:Это
d3 = d1.remove('a')
именно то, о чем вопрос.Если у вас есть изменяемые структуры данных, такие как
dict
иlist
встроенные вpmap
, у вас по-прежнему будут проблемы с алиасами - вы можете это исправить, только сделав неизменным весь путь, внедривpmap
s иpvector
s.1. HAMT также стали популярными в таких языках, как Scala, Clojure, Haskell, потому что они очень хорошо работают с программированием без блокировок и программной транзакционной памятью, но ни один из них не очень актуален в Python.
2. На самом деле, это HAMT в STDLIB, используемых в реализации
contextvars
. Ранее отозванный ПКП объясняет почему. Но это скрытая деталь реализации библиотеки, а не публичный тип коллекции.источник
Результат:
d = {1: 2, '2': 3}
источник
Просто позвоните del d ['key'].
Тем не менее, на производстве всегда полезно проверять, существует ли «ключ» в d.
источник
try-except
блоке. По крайней мере, это будет атомная операция;)d.pop('key', None)
пользуйся, это один лайнер. Но на самом деле вопрос заключался в том, чтобы получить словарь без единого ключа, а не в изменении слова. Так что понимание - это хороший выбор здесь;)Нет, другого пути нет
Тем не менее, часто создавать копии только слегка измененных словарей, вероятно, не очень хорошая идея, поскольку это приводит к сравнительно большим требованиям к памяти. Обычно лучше зарегистрировать старый словарь (если даже необходимо), а затем изменить его.
источник
источник
это не делает никакой обработки ошибок, это предполагает, что ключ находится в dict, Вы могли бы хотеть проверить это сначала, и
raise
если это неисточник
del test_dict[key]
?Здесь подход дизайна верхнего уровня:
Я передаю словарь и ключ, который я хочу, в свою функцию, проверяет, является ли это словарь, и если ключ в порядке, и если оба существуют, удаляет значение из словаря и распечатывает остатки.
Вывод:
{'B': 55, 'A': 34}
Надеюсь, это поможет!
источник
Ниже фрагмент кода поможет вам определенно, я добавил комментарии в каждой строке, которые помогут вам в понимании кода.
или вы также можете использовать dict.pop ()
или лучший подход
источник
Вот еще один вариант, использующий понимание списка:
Подход основан на ответе из этого поста: эффективный способ удаления ключей с пустыми строками.
источник
if v
кif k is not 'a'
ответам op. Но я не думаю, что это эффективный способ, это удаляет элемент в O (n), а не O (log n), как pop или del.Следующий код создаст копию dict
species
и удалит элементы, которые не находятся вtrans_HI
источник