Фильтр содержит только определенные ключи? - PullRequest
384 голосов
/ 06 августа 2010

У меня есть dict, в котором есть целая куча записей.Меня интересуют только некоторые из них.Есть ли простой способ удалить все остальные?

Ответы [ 12 ]

512 голосов
/ 06 августа 2010

Создание нового слова:

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]
83 голосов
/ 10 апреля 2014

Чуть более элегантное понимание слова:

foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}
63 голосов
/ 06 августа 2010

Вот пример в 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.

Этот метод медленнее, чем ответ Делнана, если вы хотите выбрать только несколькоочень много ключей.

19 голосов
/ 05 июня 2014

Это можно сделать с помощью функции project из моей библиотеки funcy :

from funcy import project
small_dict = project(big_dict, keys)

Также взгляните на select_keys .

17 голосов
/ 28 ноября 2013

Эта лямбда-строка должна работать:

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.

16 голосов
/ 26 июня 2017

код 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 раз для каждого фрагмента кода.

enter image description here

Для python 3.6 производительность трех способов фильтрации dict keys практически одинакова. Для Python 2.7 код 3 немного быстрее.

14 голосов
/ 06 августа 2010

Учитывая ваш оригинальный словарь orig и набор записей, которые вас интересуют keys:

filtered = dict(zip(keys, [orig[k] for k in keys]))

, что не так хорошо, как ответ Делнана, но должно работать на каждом Pythonверсия интереса.Однако он хрупок по отношению к каждому элементу keys, существующему в вашем исходном словаре.

6 голосов
/ 04 августа 2013

Эта функция поможет:

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}

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

Редактировать: Добавлена ​​отдельная функция для исключения определенных ключей из dict.

6 голосов
/ 05 июля 2013

Основано на принятом ответе delnan.

Что если один из ваших разыскиваемых ключей отсутствует в old_dict?Решение delnan выдаст исключение KeyError, которое вы можете перехватить.Если это не то, что вам нужно, возможно, вы захотите:

  1. включать только те ключи, которые существуют как в 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'}
    
  2. имеет значение по умолчанию для ключей, которое не задано в 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'}
    
1 голос
/ 27 мая 2019

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

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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...