Как я могу удалить ключ из словаря Python?

avatar
Tony
30 июня 2012 в 20:27
2077496
16
2327

При удалении ключа из словаря я использую:

if 'key' in my_dict:
    del my_dict['key']

Есть ли однострочный способ сделать это?

Источник
zigg
20 августа 2013 в 12:19
29

Сценарий тестирования для различных методов, предложенных в ответах на этот вопрос: gist.github.com/zigg/6280653

Abu Shoeb
16 января 2021 в 21:20
1

Отвечает ли это на ваш вопрос? Удалить элемент из словаря

Ответы (16)

avatar
Sven Marnach
30 июня 2012 в 20:29
3756

Чтобы удалить ключ независимо от того, находится ли он в словаре, используйте форму с двумя аргументами dict.pop():

my_dict.pop('key', None)

Это вернет my_dict[key], если key существует в словаре, и None в противном случае. Если второй параметр не указан (т. Е. my_dict.pop('key')) и key не существует, возникает KeyError.

Чтобы удалить ключ, который гарантированно существует, вы также можете использовать:

del my_dict['key']

Это вызовет KeyError, если ключ отсутствует в словаре.

kratenko
18 августа 2013 в 12:21
216

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

Salvatore Cosentino
14 июня 2017 в 02:05
8

В вопросе сохранять ценность не требуется. Это только добавит ненужной сложности. Ответ от @zigg (ниже) намного лучше.

Sven Marnach
15 июня 2017 в 13:52
15

@SalvatoreCosentino Я не могу понять ваш аргумент. Чем код в этом ответе сложнее, чем код в другом ответе?

Salvatore Cosentino
15 июня 2017 в 15:44
2

Привет @SvenMarnach, чтобы 1) На мой взгляд, ответ ниже более элегантен (например, обработка исключения) 2) использование pop в большинстве языков программирования (и структур данных) используется, когда вы хотите сохранить удаленное значение, и вопрос только об удалении ключа. Возврат значения, которое никогда не использовалось, было бы просто неэффективным.

Sven Marnach
15 июня 2017 в 18:44
48

@SalvatoreCosentino Нет, игнорирование возвращаемого значения функции вовсе не неэффективно. Напротив, это решение намного быстрее, чем решение try / except, если ключ не существует. Возможно, вам будет легче читать одно или другое, и это нормально. Оба являются идиоматическим Python, поэтому выбирайте то, что вам больше нравится. Но утверждать, что этот ответ более сложный или неэффективный, просто не имеет смысла.

user5359531
1 августа 2018 в 17:47
0

Проблема с этим подходом заключается в том, что он возвращает значение key, а не исходный dict. Итак, {'a':1, 'b':2}.pop('b') возвращает 2 вместо {'a':1}

Sven Marnach
2 августа 2018 в 10:09
6

@ user5359531 Я не понимаю. Как это проблема? Ни один из методов встроенных типов Python не возвращает self, поэтому было бы довольно удивительно, если бы это сделал этот.

user5359531
3 августа 2018 в 17:29
0

при попытке использовать эту функцию в понимании списка, что является довольно типичным вариантом использования однострочников в Python. Преобразование одного списка диктовок в другой, в котором удалены некоторые ключи.

Sven Marnach
3 августа 2018 в 17:48
4

@ user5359531 Обычно следует избегать составления списков с побочными эффектами, поскольку они сбивают с толку. Если dict.pop() вернул исходный dict, то b = [d.pop("key") for d in a] изменит оба списка , a и b, так как они будут использовать одни и те же объекты словаря. Это одна из причин, по которой в Python существует соглашение о том, что изменяющие методы не имеют возвращаемого значения. (Фактически, dict.pop() является исключением из этого соглашения, но не нарушает дух соглашения.)

Sven Marnach
3 августа 2018 в 17:50
4

@ user5359531 Если вы хотите изменить список имеющихся словарей, используйте цикл for: for d in a: d.pop("key", None). Если вы хотите сохранить исходные словари без изменений, сначала скопируйте их: b = [d.copy() for d in a].

matanster
23 мая 2020 в 08:36
0

полезный вариант использования: создание иерархии из простого словаря, как в new_dict = {my_dict.pop('key_to_promote'): my_dict}

Ambareesh
22 августа 2020 в 15:07
0

Эквивалентом структуры данных set является операция discard. Например, my_set.discard(k) удалит k без повышения KeyError, тогда как my_set.remove(k) вызовет KeyError, если k отсутствует в наборе.

avatar
Abhishek
19 апреля 2022 в 17:39
1

просто создайте копию словаря .

newMy_dict = my_dict.copy()
if 'key' in newMy_dict :
    del newMy_dict['key']

Таким образом вы можете управлять исключением.

avatar
muTheTechie
21 февраля 2022 в 16:24
0

Попробуйте это

if key in data:
   del data[key]
avatar
U12-Forward
12 сентября 2021 в 02:15
1

Вы также можете использовать filter с lambda:

>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> dict(filter(lambda x: x[0] != 'a', d.items()))
{'b': 2, 'c': 3}
>>>
avatar
Anshika Singh
21 июня 2020 в 09:24
5

Тип данных 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}

Таким образом, вы можете удалить элемент из словаря в одну строку.

avatar
ZenG
25 апреля 2020 в 16:36
3

Одиночный фильтр на кнопке

  • вернуть «ключ» и удалить его из my_dict, если «ключ» существует в my_dict
  • return None, если "key" не существует в my_dict

это заменит 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()
            )
    )
)
avatar
Sai Kiran Sangam
17 сентября 2019 в 19:25
5

Другой способ - использовать 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}
anon01
4 мая 2021 в 22:20
0

это на самом деле не выполняет то, что просят - он создает новый dict с удаленными ненужными ключами. Кроме того, перебор всех ключей для удаления одного выполняется за O (1) за время O (N).

avatar
CervEd
14 июня 2019 в 08:44
3

Я предпочитаю неизменяемую версию

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}
avatar
Alec
25 мая 2019 в 04:06
8

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

try: 
    del dict[key]

except KeyError: pass

Однако это медленнее, чем метод pop(), если ключ не существует.

my_dict.pop('key', None)

Для нескольких ключей это не имеет значения, но если вы делаете это неоднократно, то лучше использовать последний метод.

Самый быстрый подход:

if 'key' in dict: 
    del myDict['key']

Но этот метод опасен, потому что если 'key' удалить между двумя строками, будет поднят KeyError.

avatar
M.Innat
19 мая 2018 в 10:09
8

Мы можем удалить ключ из словаря 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

Вилка эта сущность для дальнейшего использования, если вы сочтете это полезным.

Rob
28 февраля 2019 в 08:35
6

Не используйте if myDict.get('one') для проверки наличия ключа! Это не удается, если myDict ['one'] имеет ложное значение. Кроме того, dicts не имеют внутреннего порядка, поэтому упоминать его не имеет смысла.

Boris
3 апреля 2020 в 08:29
0

@Rob dicts упорядочены по порядку вставки, начиная с CPython 3.6 и всех других реализаций Python, начиная с 3.7.

avatar
Sarthak Gupta
2 мая 2018 в 10:22
18

Использование ключевого слова "del":

del dict[key]
avatar
Peter Smit
7 декабря 2016 в 12:19
73

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
K--
6 апреля 2020 в 22:12
4

@Boris - это полезно в качестве общего упражнения.

Boris
6 апреля 2020 в 22:33
4

@daisy, я говорю, что вы должны выбрать наиболее читаемый синтаксис, а не операцию, которая на 300 наносекунд быстрее (это буквально разница между del и pop из первого набора таймингов выше)

Boris
6 апреля 2020 в 22:47
0

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

avatar
Shameem
7 декабря 2016 в 05:52
43

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

>>> my_dict = {k: v for k, v in my_dict.items() if k != 'key'}

Вы можете удалить по условиям. Нет ошибки, если key не существует.

Jeff D. White
5 августа 2020 в 23:33
1

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

mazunki
20 ноября 2020 в 19:51
2

Хотя, вероятно, я бы сделал это так же, но это создает в памяти совершенно новый словарь, копируя (ссылки на) объекты в новый словарь. Затем он сохраняет его под старым именем. Для больших словарей это может занять некоторое время. del dict[key] или dict.pop(key) будет быстрее во всех случаях.

avatar
Marc Maxmeister
16 сентября 2015 в 19:17
60

Если вам нужно удалить много ключей из словаря в одной строке кода, я думаю, что использование 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».

Greg Krimer
7 ноября 2015 в 16:31
44

Это не будет работать в Python 3, потому что map и друзья теперь ленивы и возвращают итераторы. Использование map для устранения побочных эффектов обычно считается плохой практикой; стандартный цикл for ... in был бы лучше. См. Представления и итераторы вместо списков для получения дополнительной информации.

Michael Ekoka
22 октября 2017 в 08:48
5

Независимо от вкуса и стиля практики, понимание списков должно работать в Py3 [myDict.pop(i, None) for i in ['a', 'c']], поскольку они предлагают общую альтернативу mapfilter).

Boris
3 апреля 2020 в 08:32
1

@MichaelEkoka, вы не должны использовать составление списков из-за их побочных эффектов, используйте обычный цикл for ... in.

Michael Ekoka
7 апреля 2020 в 14:06
0

@ Борис Вы, наверное, правы. Мой ответ конкретно относится к использованию map(), которое часто используется из-за его побочных эффектов. Рекомендуемая альтернатива в Python - это понимание списка, которое, на мой взгляд, все еще довольно читабельно и когнитивно легкое как однострочное (см. Вопрос). Обе конструкции, используемые только из-за своих побочных эффектов, действительно приводят к бесполезному списку, который может быть неэффективным. Что касается Python3, я не знаю встроенной функции, которая может безопасно и элегантно выполнять итерацию через выражение генератора без дорогостоящих побочных продуктов, например. loop(d.pop(k) for k in ['a', 'b']).

Marc Maxmeister
8 апреля 2020 в 03:20
0

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

Boris
4 мая 2020 в 14:18
1

@MichaelEkoka "встроенная функция" - это цикл for: for k in ['a', 'b']: d.pop(k). Зачем нужен другой способ? Если вам нужно, чтобы он занимал только одну строку, вы можете поместить вторую часть цикла for в ту же строку.

Michael Ekoka
4 мая 2020 в 15:18
0

@Boris Как я уже сказал, мой ответ относится к , в частности, к использованию map()filter()), что означает, что если вам нужно использовать любой из этих двух, вы можете просто использовать понимание списка. Я также признаю, что и понимание списка, и map() расточительны, поскольку они создают ненужный список в качестве побочного продукта. Остается, что их более функциональный синтаксис по-прежнему ценится и желателен многими программистами (например, coderhelper.com/q/1080026/56974). Это вопрос стиля. К сожалению, Python не предлагает встроенного функционального способа зацикливания и выполнения без побочных продуктов.

avatar
Akavall
4 марта 2013 в 16:43
177

Мне потребовалось некоторое время, чтобы понять, что именно делает my_dict.pop("key", None). Поэтому я добавлю это как ответ, чтобы сэкономить время на поиске в Google:

pop(key[, default])

Если ключ находится в словаре, удалите его и верните его значение, иначе вернуть по умолчанию . Если по умолчанию не указан и ​​ключ отсутствует в словарь, поднимается KeyError.

Документация

David Mulder
6 августа 2013 в 18:07
21

Просто введите help (dict.pop) в интерпретаторе Python.

David Mulder
6 августа 2013 в 18:08
17

help () и dir () могут быть вашими друзьями, когда вам нужно знать, что что-то делает.

Erik Kaplun
13 апреля 2014 в 01:09
4

или dict.pop? в IPython.

avatar
zigg
30 июня 2012 в 20:36
405

В частности, чтобы ответить «есть ли однострочный способ сделать это?»

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

что, конечно, определенно не однострочное.

zigg
1 июля 2012 в 16:30
32

Да, pop определенно более краткий, хотя есть одно ключевое преимущество такого способа: сразу становится понятно, что он делает.

Chris Barker
20 августа 2013 в 05:01
6

Оператор try/except стоит дороже. Исключение возникает медленно.

zigg
20 августа 2013 в 12:18
18

@ChrisBarker Я обнаружил, что если ключ существует, try немного быстрее, а если нет, try действительно намного медленнее. pop довольно согласован, но медленнее, чем все, кроме try с отсутствующим ключом. См. gist.github.com/zigg/6280653. В конечном счете, это зависит от того, как часто вы ожидаете, что ключ действительно будет в словаре, и от того, нужна ли вам атомарность - и, конечно же, от того, участвуете ли вы в преждевременной оптимизации;)

Juan Carlos Coto
30 июня 2014 в 21:15
10

Я считаю, что нельзя упускать из виду ценность ясности. +1 за это.

Marc
9 июля 2015 в 18:00
3

Что касается расходов на попытку / за исключением, вы также можете пойти if 'key' in mydict: #then del.... Мне нужно было вытащить ключ / val из dict для правильного анализа, pop не было идеальным решением.

zigg
14 июля 2015 в 13:25
1

@datamafia Однако, как и все решения if k in d, это не атомарно, и del может дать сбой. Почему pop у вас не сработал?

Marc
14 июля 2015 в 15:42
0

@zigg У меня была шаткая структура данных, короче говоря, мне нужно было заказать dict через пару ключ / val, вложенную в dict. Поэтому я использовал if key in, чтобы определить, находится ли ключ устранения проблемы в dict, скопировать во временный dict, выполнить упорядочение lambda / list comp ordering dict, а затем добавить значение обратно. Pop и del работают одинаково в этом случае. Условный квалификатор позволял поместить ключ / val в temp dict для выполнения работы. Это была работа для некоторого коричневого кода, не идеальная, но мы двинулись дальше. pop() тоже сработало бы, мне нравится многословие. Попробовать / поймать может быть дорого.

PythonTester
11 марта 2016 в 16:01
0

Попробуй поймать - это «правильный способ» сделать это. это не неловко.

Gloweye
29 августа 2018 в 08:14
1

@Marc, если вам нужно обработать пару ключ: значение, используйте вместо этого popitem(). Поместите его в цикл while, чтобы использовать весь dict.

juan Isaza
5 марта 2021 в 16:00
0

@ChrisBarker Python - это язык, предназначенный для управления исключениями, они лишь немного медленнее, чем другие варианты, см .: coderhelper.com/questions/2522005/…