При удалении ключа из словаря я использую:
if 'key' in my_dict:
del my_dict['key']
Есть ли однострочный способ сделать это?
При удалении ключа из словаря я использую:
if 'key' in my_dict:
del my_dict['key']
Есть ли однострочный способ сделать это?
Чтобы удалить ключ независимо от того, находится ли он в словаре, используйте форму с двумя аргументами dict.pop()
:
my_dict.pop('key', None)
Это вернет my_dict[key]
, если key
существует в словаре, и None
в противном случае. Если второй параметр не указан (т. Е. my_dict.pop('key')
) и key
не существует, возникает KeyError
.
Чтобы удалить ключ, который гарантированно существует, вы также можете использовать:
del my_dict['key']
Это вызовет KeyError
, если ключ отсутствует в словаре.
Иногда преимущество использования pop()
перед del
: он возвращает значение для этого ключа. Таким образом, вы можете получить и удалить запись из dict в одной строке кода.
В вопросе сохранять ценность не требуется. Это только добавит ненужной сложности. Ответ от @zigg (ниже) намного лучше.
@SalvatoreCosentino Я не могу понять ваш аргумент. Чем код в этом ответе сложнее, чем код в другом ответе?
Привет @SvenMarnach, чтобы 1) На мой взгляд, ответ ниже более элегантен (например, обработка исключения) 2) использование pop в большинстве языков программирования (и структур данных) используется, когда вы хотите сохранить удаленное значение, и вопрос только об удалении ключа. Возврат значения, которое никогда не использовалось, было бы просто неэффективным.
@SalvatoreCosentino Нет, игнорирование возвращаемого значения функции вовсе не неэффективно. Напротив, это решение намного быстрее, чем решение try
/ except
, если ключ не существует. Возможно, вам будет легче читать одно или другое, и это нормально. Оба являются идиоматическим Python, поэтому выбирайте то, что вам больше нравится. Но утверждать, что этот ответ более сложный или неэффективный, просто не имеет смысла.
Проблема с этим подходом заключается в том, что он возвращает значение key
, а не исходный dict. Итак, {'a':1, 'b':2}.pop('b')
возвращает 2
вместо {'a':1}
@ user5359531 Я не понимаю. Как это проблема? Ни один из методов встроенных типов Python не возвращает self
, поэтому было бы довольно удивительно, если бы это сделал этот.
при попытке использовать эту функцию в понимании списка, что является довольно типичным вариантом использования однострочников в Python. Преобразование одного списка диктовок в другой, в котором удалены некоторые ключи.
@ user5359531 Обычно следует избегать составления списков с побочными эффектами, поскольку они сбивают с толку. Если dict.pop()
вернул исходный dict, то b = [d.pop("key") for d in a]
изменит оба списка , a
и b
, так как они будут использовать одни и те же объекты словаря. Это одна из причин, по которой в Python существует соглашение о том, что изменяющие методы не имеют возвращаемого значения. (Фактически, dict.pop()
является исключением из этого соглашения, но не нарушает дух соглашения.)
@ user5359531 Если вы хотите изменить список имеющихся словарей, используйте цикл for: for d in a: d.pop("key", None)
. Если вы хотите сохранить исходные словари без изменений, сначала скопируйте их: b = [d.copy() for d in a]
.
полезный вариант использования: создание иерархии из простого словаря, как в new_dict = {my_dict.pop('key_to_promote'): my_dict}
Эквивалентом структуры данных set
является операция discard
. Например, my_set.discard(k)
удалит k без повышения KeyError, тогда как my_set.remove(k)
вызовет KeyError, если k
отсутствует в наборе.
просто создайте копию словаря .
newMy_dict = my_dict.copy()
if 'key' in newMy_dict :
del newMy_dict['key']
Таким образом вы можете управлять исключением.
Вы также можете использовать filter
с lambda
:
>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> dict(filter(lambda x: x[0] != 'a', d.items()))
{'b': 2, 'c': 3}
>>>
Тип данных Dictionary имеет метод под названием dict_name.pop(item)
, который можно использовать для удаления пары ключ: значение из словаря.
a={9:4,2:3,4:2,1:3}
a.pop(9)
print(a)
Это даст результат как:
{2: 3, 4: 2, 1: 3}
Таким образом, вы можете удалить элемент из словаря в одну строку.
это заменит
my_dict
на месте (изменяемый)
my_dict.pop('key', None)
создать новый dict (неизменяемый)
dic1 = {
"x":1,
"y": 2,
"z": 3
}
def func1(item):
return item[0]!= "x" and item[0] != "y"
print(
dict(
filter(
lambda item: item[0] != "x" and item[0] != "y",
dic1.items()
)
)
)
Другой способ - использовать items () + dict computing.
items () в сочетании с пониманием dict также может помочь нам в решении задачи удаления пары ключ-значение, но у него есть недостаток, заключающийся в том, что он не является техникой dict на месте. Фактически, новый dict, если он создан, за исключением ключа, который мы не хотим включать.
test_dict = {"sai" : 22, "kiran" : 21, "vinod" : 21, "sangam" : 21}
# Printing dictionary before removal
print ("dictionary before performing remove is : " + str(test_dict))
# Using items() + dict comprehension to remove a dict. pair
# removes vinod
new_dict = {key:val for key, val in test_dict.items() if key != 'vinod'}
# Printing dictionary after removal
print ("dictionary after remove is : " + str(new_dict))
Вывод:
dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}
это на самом деле не выполняет то, что просят - он создает новый dict с удаленными ненужными ключами. Кроме того, перебор всех ключей для удаления одного выполняется за O (1) за время O (N).
Я предпочитаю неизменяемую версию
foo = {
1:1,
2:2,
3:3
}
removeKeys = [1,2]
def woKeys(dct, keyIter):
return {
k:v
for k,v in dct.items() if k not in keyIter
}
>>> print(woKeys(foo, removeKeys))
{3: 3}
>>> print(foo)
{1: 1, 2: 2, 3: 3}
Вы можете использовать обработку исключений, если хотите быть очень подробным:
try:
del dict[key]
except KeyError: pass
Однако это медленнее, чем метод pop()
, если ключ не существует.
my_dict.pop('key', None)
Для нескольких ключей это не имеет значения, но если вы делаете это неоднократно, то лучше использовать последний метод.
Самый быстрый подход:
if 'key' in dict:
del myDict['key']
Но этот метод опасен, потому что если 'key'
удалить между двумя строками, будет поднят KeyError
.
Мы можем удалить ключ из словаря Python одним из следующих способов.
Использование ключевого слова del
; это почти тот же подход, что и вы -
myDict = {'one': 100, 'two': 200, 'three': 300 }
print(myDict) # {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : del myDict['one']
print(myDict) # {'two': 200, 'three': 300}
Или
Мы можем сделать следующее:
Но следует иметь в виду, что в этом процессе фактически не удаляет какой-либо ключ из словаря, а не делает определенный ключ исключенным из этого словаря. Вдобавок я заметил, что он вернул словарь, который не был упорядочен так же, как myDict
.
myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
{key:value for key, value in myDict.items() if key != 'one'}
Если мы запустим его в оболочке, он выполнит что-то вроде {'five': 500, 'four': 400, 'three': 300, 'two': 200}
- обратите внимание, что это не тот же порядок, что и myDict
. Опять же, если мы попытаемся вывести myDict
, то увидим все ключи, включая те, которые мы исключили из словаря с помощью этого подхода. Однако мы можем создать новый словарь, присвоив переменной следующий оператор:
var = {key:value for key, value in myDict.items() if key != 'one'}
Теперь, если мы попытаемся распечатать его, он будет следовать родительскому порядку:
print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500}
Или
Используя метод pop()
.
myDict = {'one': 100, 'two': 200, 'three': 300}
print(myDict)
if myDict.get('one') : myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
Разница между del
и pop
заключается в том, что с помощью метода pop()
мы можем сохранить значение ключа , если необходимо, например:
myDict = {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : var = myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
print(var) # 100
Вилка эта сущность для дальнейшего использования, если вы сочтете это полезным.
Не используйте if myDict.get('one')
для проверки наличия ключа! Это не удается, если myDict ['one'] имеет ложное значение. Кроме того, dicts не имеют внутреннего порядка, поэтому упоминать его не имеет смысла.
@Rob dicts упорядочены по порядку вставки, начиная с CPython 3.6 и всех других реализаций Python, начиная с 3.7.
del my_dict[key]
немного быстрее, чем my_dict.pop(key)
для удаления ключа из словаря, когда ключ существует
>>> import timeit
>>> setup = "d = {i: i for i in range(100000)}"
>>> timeit.timeit("del d[3]", setup=setup, number=1)
1.79e-06
>>> timeit.timeit("d.pop(3)", setup=setup, number=1)
2.09e-06
>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)
0.00786
Но когда ключ не существует, if key in my_dict: del my_dict[key]
работает немного быстрее, чем my_dict.pop(key, None)
. Оба они как минимум в три раза быстрее, чем del
в операторе try
/ except
:
>>> timeit.timeit("if 'missing key' in d: del d['missing key']", setup=setup)
0.0229
>>> timeit.timeit("d.pop('missing key', None)", setup=setup)
0.0426
>>> try_except = """
... try:
... del d['missing key']
... except KeyError:
... pass
... """
>>> timeit.timeit(try_except, setup=setup)
0.133
@Boris - это полезно в качестве общего упражнения.
@daisy, я говорю, что вы должны выбрать наиболее читаемый синтаксис, а не операцию, которая на 300 наносекунд быстрее (это буквально разница между del
и pop
из первого набора таймингов выше)
Кроме того, эти операции выполняются настолько быстро, что эти тайминги ненадежны.
Вы можете использовать понимание словаря, чтобы создать новый словарь с удаленным ключом:
>>> my_dict = {k: v for k, v in my_dict.items() if k != 'key'}
Вы можете удалить по условиям. Нет ошибки, если key
не существует.
Этот ответ отличается от других, потому что у него нет побочных эффектов (он не изменяет исходный словарь).
Хотя, вероятно, я бы сделал это так же, но это создает в памяти совершенно новый словарь, копируя (ссылки на) объекты в новый словарь. Затем он сохраняет его под старым именем. Для больших словарей это может занять некоторое время. del dict[key]
или dict.pop(key)
будет быстрее во всех случаях.
Если вам нужно удалить много ключей из словаря в одной строке кода, я думаю, что использование map () будет довольно кратким и читаемым Pythonic:
myDict = {'a':1,'b':2,'c':3,'d':4}
map(myDict.pop, ['a','c']) # The list of keys to remove
>>> myDict
{'b': 2, 'd': 4}
И если вам нужно отловить ошибки, когда вы вставляете значение, которого нет в словаре, используйте лямбда внутри map () следующим образом:
map(lambda x: myDict.pop(x,None), ['a', 'c', 'e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4}
или в python3
вместо этого вы должны использовать понимание списка:
[myDict.pop(x, None) for x in ['a', 'c', 'e']]
Работает. И «e» не вызывало ошибки, даже если myDict не имел ключа «e».
Это не будет работать в Python 3, потому что map
и друзья теперь ленивы и возвращают итераторы. Использование map
для устранения побочных эффектов обычно считается плохой практикой; стандартный цикл for ... in
был бы лучше. См. Представления и итераторы вместо списков для получения дополнительной информации.
Независимо от вкуса и стиля практики, понимание списков должно работать в Py3 [myDict.pop(i, None) for i in ['a', 'c']]
, поскольку они предлагают общую альтернативу map
(и filter
).
@MichaelEkoka, вы не должны использовать составление списков из-за их побочных эффектов, используйте обычный цикл for ... in
.
@ Борис Вы, наверное, правы. Мой ответ конкретно относится к использованию map()
, которое часто используется из-за его побочных эффектов. Рекомендуемая альтернатива в Python - это понимание списка, которое, на мой взгляд, все еще довольно читабельно и когнитивно легкое как однострочное (см. Вопрос). Обе конструкции, используемые только из-за своих побочных эффектов, действительно приводят к бесполезному списку, который может быть неэффективным. Что касается Python3, я не знаю встроенной функции, которая может безопасно и элегантно выполнять итерацию через выражение генератора без дорогостоящих побочных продуктов, например. loop(d.pop(k) for k in ['a', 'b'])
.
Меня забавляет, что в мой самый популярный ответ за все время включены некоторые хаки, которые я бы никогда не использовал. Понимание списка (вариант 3), на мой взгляд, является наименее плохим подходом. Используйте это.
@MichaelEkoka "встроенная функция" - это цикл for: for k in ['a', 'b']: d.pop(k)
. Зачем нужен другой способ? Если вам нужно, чтобы он занимал только одну строку, вы можете поместить вторую часть цикла for в ту же строку.
@Boris Как я уже сказал, мой ответ относится к , в частности, к использованию map()
(и filter()
), что означает, что если вам нужно использовать любой из этих двух, вы можете просто использовать понимание списка. Я также признаю, что и понимание списка, и map()
расточительны, поскольку они создают ненужный список в качестве побочного продукта. Остается, что их более функциональный синтаксис по-прежнему ценится и желателен многими программистами (например, coderhelper.com/q/1080026/56974). Это вопрос стиля. К сожалению, Python не предлагает встроенного функционального способа зацикливания и выполнения без побочных продуктов.
Мне потребовалось некоторое время, чтобы понять, что именно делает my_dict.pop("key", None)
. Поэтому я добавлю это как ответ, чтобы сэкономить время на поиске в Google:
pop(key[, default])
Если ключ находится в словаре, удалите его и верните его значение, иначе вернуть по умолчанию . Если по умолчанию не указан и ключ отсутствует в словарь, поднимается
KeyError
.
Просто введите help (dict.pop) в интерпретаторе Python.
help () и dir () могут быть вашими друзьями, когда вам нужно знать, что что-то делает.
или dict.pop?
в IPython.
В частности, чтобы ответить «есть ли однострочный способ сделать это?»
if 'key' in my_dict: del my_dict['key']
... ну, вы спросили ;-)
Однако следует учитывать, что этот способ удаления объекта из dict
является не атомарным - возможно, что 'key'
может находиться в операторе <428712542634287> во время оператора , но может быть удален до выполнения del
, и в этом случае del
завершится ошибкой с KeyError
. Учитывая это, было бы безопаснее использовать dict.pop или что-то вроде
try:
del my_dict['key']
except KeyError:
pass
что, конечно, определенно не однострочное.
Да, pop
определенно более краткий, хотя есть одно ключевое преимущество такого способа: сразу становится понятно, что он делает.
Оператор try/except
стоит дороже. Исключение возникает медленно.
@ChrisBarker Я обнаружил, что если ключ существует, try
немного быстрее, а если нет, try
действительно намного медленнее. pop
довольно согласован, но медленнее, чем все, кроме try
с отсутствующим ключом. См. gist.github.com/zigg/6280653. В конечном счете, это зависит от того, как часто вы ожидаете, что ключ действительно будет в словаре, и от того, нужна ли вам атомарность - и, конечно же, от того, участвуете ли вы в преждевременной оптимизации;)
Я считаю, что нельзя упускать из виду ценность ясности. +1 за это.
Что касается расходов на попытку / за исключением, вы также можете пойти if 'key' in mydict: #then del...
. Мне нужно было вытащить ключ / val из dict для правильного анализа, pop не было идеальным решением.
@datamafia Однако, как и все решения if k in d
, это не атомарно, и del
может дать сбой. Почему pop
у вас не сработал?
@zigg У меня была шаткая структура данных, короче говоря, мне нужно было заказать dict через пару ключ / val, вложенную в dict. Поэтому я использовал if key in
, чтобы определить, находится ли ключ устранения проблемы в dict, скопировать во временный dict, выполнить упорядочение lambda / list comp ordering dict, а затем добавить значение обратно. Pop и del работают одинаково в этом случае. Условный квалификатор позволял поместить ключ / val в temp dict для выполнения работы. Это была работа для некоторого коричневого кода, не идеальная, но мы двинулись дальше. pop()
тоже сработало бы, мне нравится многословие. Попробовать / поймать может быть дорого.
Попробуй поймать - это «правильный способ» сделать это. это не неловко.
@Marc, если вам нужно обработать пару ключ: значение, используйте вместо этого popitem()
. Поместите его в цикл while, чтобы использовать весь dict.
@ChrisBarker Python - это язык, предназначенный для управления исключениями, они лишь немного медленнее, чем другие варианты, см .: coderhelper.com/questions/2522005/…
Сценарий тестирования для различных методов, предложенных в ответах на этот вопрос: gist.github.com/zigg/6280653
Отвечает ли это на ваш вопрос? Удалить элемент из словаря