Возвращает копию словаря, исключая указанные ключи

Я хочу сделать функцию, которая возвращает копию словаря, за исключением ключей, указанных в списке.

Учитывая этот словарь:

my_dict = {
    "keyA": 1,
    "keyB": 2,
    "keyC": 3
}

Вызов without_keys(my_dict, ['keyB', 'keyC']) должен вернуть:

{
    "keyA": 1
}

Я хотел бы сделать это в одну строку с аккуратным пониманием словаря, но у меня проблемы. Моя попытка такова:

def without_keys(d, keys):
    return {k: d[f] if k not in keys for f in d}

что является недопустимым синтаксисом. Как я могу это сделать?


person Juicy    schedule 15.07.2015    source источник


Ответы (6)


Вы были близки, попробуйте фрагмент ниже:

>>> my_dict = {
...     "keyA": 1,
...     "keyB": 2,
...     "keyC": 3
... }
>>> invalid = {"keyA", "keyB"}
>>> def without_keys(d, keys):
...     return {x: d[x] for x in d if x not in keys}
>>> without_keys(my_dict, invalid)
{'keyC': 3}

По сути, if k not in keys будет идти в конце понимания dict в приведенном выше случае.

person Anshul Goyal    schedule 15.07.2015
comment
Вы объявили недействительным набор. Есть ли причина для этого? Достаточно ли будет списка? - person Prithvi Boinpally; 23.10.2020
comment
Да, списка тоже будет достаточно (вы можете попробовать), но обычно, когда порядок для вас не важен, предпочтительнее set (даже с точки зрения производительности, которая не важна в этом коротком примере с несколькими данными). - person Nerxis; 10.12.2020
comment
Это быстрее, чем получить все ключи, а затем вручную пропустить ненужные ключи с помощью цикла for? - person sebko_iic; 24.12.2020

В вашем понимании словаря вы должны перебирать свой словарь (не k , не уверен, что это такое). Пример -

return {k:v for k,v in d.items() if k not in keys}
person Anand S Kumar    schedule 15.07.2015
comment
Я предпочитаю это решение немного больше, потому что оно делает (крошечную) экономию, не вызывая операцию индекса d[x]. - person Alejandro Piad; 17.01.2019
comment
хотя это мелкая копия - person Eissa N.; 19.02.2021

Это должно сработать для вас.

def without_keys(d, keys):
    return {k: v for k, v in d.items() if k not in keys}
person Morgan Thrapp    schedule 15.07.2015

Еще короче. По-видимому, Python 3 позволяет вам «вычесть» list из dict_keys.

def without_keys(d, keys):
    return {k: d[k] for k in d.keys() - keys}
person Mike Fogel    schedule 17.09.2020
comment
Обратите внимание, что использование keys() вместо items() примерно на 33% медленнее: discuss.python.org/t/copy-a-dictionary-except-some-keys/2559/5 - person Tuukka Mustonen; 16.12.2020

Для тех, кто не любит понимание списка, это моя версия:

def without_keys(d, *keys):
     return dict(filter(lambda key_value: key_value[0] not in keys, d.items()))

Использование:

>>> d={1:3, 5:7, 9:11, 13:15}
>>> without_keys(d, 1, 5, 9)
{13: 15}
>>> without_keys(d, 13)
{1: 3, 5: 7, 9: 11}
>>> without_keys(d, *[5, 7])
{1: 3, 13: 15, 9: 11}
person Himel Das    schedule 02.01.2017

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

def without_keys(d, ex): 
    for i in ex: d.pop(i) 
    return d

Демо:

In [11]: my_dict = { 
    ...:     "keyA": 1, 
    ...:     "keyB": 2, 
    ...:     "keyC": 3 
    ...: }                                                                                                                                                                                                  

In [12]:                                                                                                                                                                                                    

In [12]: def without_keys(d, ex): 
    ...:     for i in ex: d.pop(i) 
    ...:     return d 
    ...:                                                                                                                                                                                                    

In [13]: without_keys(my_dict, ['keyB', 'keyC'])                                                                                                                                                            
Out[13]: {'keyA': 1}
person kasravnd    schedule 01.02.2020
comment
Я бы пошел по тому же пути и удалил ключи; но это имеет большое значение с другими предложениями: исходный dict изменен. Если мы можем принять это прекрасно. В противном случае я бы просто начал с d.copy() перед удалением. - person kriss; 04.12.2020