У мене 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')
напевно.
Ви можете зробити це за допомогою функції проекту з моєї цікавої бібліотеки:
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}
Всі показники продуктивності коду вимірюються за часом, використовуючи число = 1000, і збирають 1000 разів для кожного фрагмента коду.
Для python 3.6 продуктивність трьох способів клавіш диктування фільтрів майже однакова. Для 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
існують у вашому оригінальному словнику.
На підставі прийнятої відповіді делнан.
Що робити, якщо один із шуканих ключів не вказаний у старій версії? Рішення 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'}
{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, операція не проводиться на місці, тому продуктивність пов'язана з кількістю клавіш у словнику. Однак перевага цього полягає в тому, що функція не змінює наданий словник.
Редагувати: Додано окрему функцію для виключення певних клавіш із диктату.
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()
не, а dict
.
filtered
в dict
і ви отримаєте назад словник!
Ось ще один простий метод використання del
в одному вкладиші:
for key in e_keys: del your_dict[key]
e_keys
- це список ключів, які потрібно виключити. Це оновить ваш дикт, а не дасть вам новий.
Якщо ви хочете новий вихідний дікт, то перед видаленням зробіть його копію:
new_dict = your_dict.copy() #Making copy of dict
for key in e_keys: del new_dict[key]
Ви можете використовувати python-benedict
, це підклас диктату.
Установка: 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
Відмова: Я автор цієї бібліотеки.