У меня dict
есть целая куча записей. Меня интересуют только некоторые из них. Есть ли простой способ удалить все остальные?
У меня dict
есть целая куча записей. Меня интересуют только некоторые из них. Есть ли простой способ удалить все остальные?
Ответы:
Построение нового диктата:
dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }
Использует словарное понимание.
Если вы используете версию, в которой их нет (например, Python 2.6 и более ранние версии), сделайте это dict((your_key, old_dict[your_key]) for ...)
. Это то же самое, хотя и хуже.
Обратите внимание, что это, в отличие от версии jnnnnn, имеет стабильную производительность (зависит только от количества ваших_ключей) для old_dict
s любого размера. И с точки зрения скорости и памяти. Поскольку это выражение генератора, оно обрабатывает один элемент за раз и не просматривает все элементы old_dict.
Удаление всего на месте:
unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]
old_dict
случаев, когда пропущенный ключ указывает на ошибку в другом месте, и в этом случае я очень предпочитаю ошибку, а не просто неверные результаты.
Чуть более элегантное понимание:
foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}
mydict.iteritems()
вместо этого. .items()
создает другой список.
Вот пример в Python 2.6:
>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}
Фильтрующая часть - это if
утверждение.
Этот метод медленнее, чем ответ Делнана, если вы хотите выбрать только несколько из очень многих ключей.
if key in ('x','y','z')
я думаю.
Вы можете сделать это с помощью функции проекта из моей библиотеки funcy :
from funcy import project
small_dict = project(big_dict, keys)
Также взгляните на select_keys .
Код 1:
dict = { key: key * 10 for key in range(0, 100) }
d1 = {}
for key, value in dict.items():
if key % 2 == 0:
d1[key] = value
Код 2:
dict = { key: key * 10 for key in range(0, 100) }
d2 = {key: value for key, value in dict.items() if key % 2 == 0}
Код 3:
dict = { key: key * 10 for key in range(0, 100) }
d3 = { key: dict[key] for key in dict.keys() if key % 2 == 0}
Производительность всех частей кода измеряется с помощью timeit, используя число = 1000, и собирается 1000 раз для каждого фрагмента кода.
Для python 3.6 производительность трех способов фильтрации ключей dict практически одинакова. Для Python 2.7 код 3 немного быстрее.
Этот лайнер лямбда должен работать:
dictfilt = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])
Вот пример:
my_dict = {"a":1,"b":2,"c":3,"d":4}
wanted_keys = ("c","d")
# run it
In [10]: dictfilt(my_dict, wanted_keys)
Out[10]: {'c': 3, 'd': 4}
Это базовое понимание списка, повторяющееся над вашими ключами dict (i в x), и выводит список пар кортежей (ключ, значение), если ключ находится в вашем желаемом списке ключей (y). Dict () оборачивает все это для вывода как объект dict.
set
для wanted_keys
, но в остальном выглядит хорошо.
dictfilt({'x':['wefwef',52],'y':['iuefiuef','efefij'],'z':['oiejf','iejf']}, ('x','z'))
он возвращается {'x': ['wefwef', 52], 'z': ['oiejf', 'iejf']}
как задумано.
dict={'0':[1,3], '1':[0,2,4], '2':[1,4]}
и результат был {}
, который я принял за чистый диктат.
foo = {'0':[1,3], '1':[0,2,4], '2':[1,4]}; dictfilt(foo,('0','2'))
я получаю: {'0': [1, 3], '2': [1, 4]}
Учитывая ваш оригинальный словарь orig
и набор записей, которые вас интересуют keys
:
filtered = dict(zip(keys, [orig[k] for k in keys]))
что не так приятно, как ответ Делнана, но должно работать в любой интересующей версии Python. Однако он хрупок по отношению к каждому элементу, keys
существующему в исходном словаре.
На основании принятого ответа Делнана.
Что если один из ваших разыскиваемых ключей отсутствует в old_dict? Решение delnan выдаст исключение KeyError, которое вы можете перехватить. Если это не то, что вам нужно, может быть, вы хотите:
включайте только ключи, которые исключаются как из old_dict, так и из вашего набора wanted_keys.
old_dict = {'name':"Foobar", 'baz':42}
wanted_keys = ['name', 'age']
new_dict = {k: old_dict[k] for k in set(wanted_keys) & set(old_dict.keys())}
>>> new_dict
{'name': 'Foobar'}
иметь значение по умолчанию для ключей, которые не установлены в old_dict.
default = None
new_dict = {k: old_dict[k] if k in old_dict else default for k in wanted_keys}
>>> new_dict
{'age': None, 'name': 'Foobar'}
{k: old_dict.get(k, default) for k in ...}
Эта функция сделает свое дело:
def include_keys(dictionary, keys):
"""Filters a dict by only including certain keys."""
key_set = set(keys) & set(dictionary.keys())
return {key: dictionary[key] for key in key_set}
Как и версия delnan, в этой версии используется словарное понимание и стабильная производительность для больших словарей (зависит только от количества разрешенных вами ключей, а не от общего количества ключей в словаре).
И так же, как и версия MyGGan, эта позволяет вашему списку ключей включать ключи, которые могут отсутствовать в словаре.
И в качестве бонуса, вот обратное, где вы можете создать словарь, исключив определенные ключи в оригинале:
def exclude_keys(dictionary, keys):
"""Filters a dict by excluding certain keys."""
key_set = set(dictionary.keys()) - set(keys)
return {key: dictionary[key] for key in key_set}
Обратите внимание, что в отличие от версии delnan, операция не выполняется на месте, поэтому производительность зависит от количества ключей в словаре. Однако преимущество этого в том, что функция не будет изменять предоставленный словарь.
Редактировать: Добавлена отдельная функция для исключения определенных ключей из dict.
invert
подразумевает ли это, что keys
аргумент сохраняется или что keys
аргумент отклонен?», Сколько из них согласится?
Если мы хотим создать новый словарь с удаленными выбранными ключами, мы можем использовать словарное понимание.
Например:
d = {
'a' : 1,
'b' : 2,
'c' : 3
}
x = {key:d[key] for key in d.keys() - {'c', 'e'}} # Python 3
y = {key:d[key] for key in set(d.keys()) - {'c', 'e'}} # Python 2.*
# x is {'a': 1, 'b': 2}
# y is {'a': 1, 'b': 2}
Другой вариант:
content = dict(k1='foo', k2='nope', k3='bar')
selection = ['k1', 'k3']
filtered = filter(lambda i: i[0] in selection, content.items())
Но вы получаете list
(Python 2) или итератор (Python 3), возвращенный filter()
, а не a dict
.
filtered
в dict
и вы получите обратно словарь!
Вот еще один простой метод, использующий del
в одном вкладыше:
for key in e_keys: del your_dict[key]
e_keys
список ключей, которые нужно исключить Это обновит ваш диктант, а не даст вам новый.
Если вы хотите новый вывод dict, то сделайте копию dict перед удалением:
new_dict = your_dict.copy() #Making copy of dict
for key in e_keys: del new_dict[key]
Вы могли бы использовать python-benedict
, это подкласс dict.
Установка: pip install python-benedict
from benedict import benedict
dict_you_want = benedict(your_dict).subset(keys=['firstname', 'lastname', 'email'])
Это открытый исходный код на GitHub: https://github.com/fabiocaccamo/python-benedict
Отказ от ответственности: я автор этой библиотеки.