У меня есть dict
, который содержит целую кучу записей. Меня интересуют только некоторые из них. Есть ли простой способ обрезать все остальные?
Фильтр dict содержит только определенные клавиши?
Ответ 1
Построение нового 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, имеет стабильную производительность (зависит только от количества ваших_keys) для old_dict
любого размера. Как с точки зрения скорости, так и с памятью. Поскольку это выражение генератора, он обрабатывает один элемент за раз, и он не просматривает все элементы old_dict.
Удаление всего на месте:
unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]
Ответ 2
Чуть более элегантное понимание диктата:
foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}
Ответ 3
Вот пример в 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
.
Этот метод медленнее, чем ответ delnan, если вы хотите только выбрать несколько очень многих клавиш.
Ответ 4
Вы можете сделать это с помощью project из моего funcy:
from funcy import project
small_dict = project(big_dict, keys)
Также посмотрите select_keys.
Ответ 5
Этот один лайнер должен работать:
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). A dict() обертывает все, что выводится как объект dict.
Ответ 6
Код 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 с использованием number = 1000 и собираются 1000 раз для каждой части кода.
Для python 3.6 производительность трех способов фильтрации ключей dict почти одинакова. Для python 2.7 код 3 немного быстрее.
Ответ 7
Учитывая ваш оригинальный словарь orig
и набор записей, которые вас интересуют keys
:
filtered = dict(zip(keys, [orig[k] for k in keys]))
который не так хорош, как ответ delnan, но должен работать в каждой интересующей Python версии. Он, однако, является хрупким для каждого элемента keys
, существующего в вашем исходном словаре.
Ответ 8
На основании принятого ответа delnan.
Что делать, если один из ваших желаемых ключей не находится в old_dict? Решение delnan выдает исключение KeyError, которое вы можете поймать. Если это не то, что вам нужно, возможно, вы хотите:
-
включают только ключи, которые активируют как в old_dict, так и в вашем наборе желаемых клавиш.
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'}
Ответ 9
Эта функция выполнит трюк:
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.
Ответ 10
Другой вариант:
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()
, а не dict
.
Ответ 11
Короткая форма:
[s.pop(k) for k in list(s.keys()) if k not in keep]
Как следует из большинства ответов, чтобы сохранить краткость, мы должны создать дублирующий объект, будь то list
или dict
. Это создает отбрасывание list
, но удаляет ключи в оригинале dict
.
Ответ 12
Если мы хотим создать новый словарь с удаленными выбранными ключами, мы можем использовать словарное понимание
Например:
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}
Ответ 13
Вот еще один простой метод с использованием del
в одном вкладыше:
for key in e_keys: del your_dict[key]
e_keys
- список исключаемых ключей. Это обновит ваш диктант, а не даст вам новый.
Если вы хотите создать новый выходной файл dict, сделайте его копию перед удалением:
new_dict = your_dict.copy() #Making copy of dict
for key in e_keys: del new_dict[key]