Фильтрация словарей и создание под-словарей на основе ключей / значений в Python? - PullRequest
5 голосов
/ 01 августа 2009

Хорошо, я застрял, с этого момента нужна помощь ...

Если у меня есть основной словарь, подобный этому:

data = [ {"key1": "value1", "key2": "value2", "key1": "value3"},  
{"key1": "value4", "key2": "value5", "key1": "value6"}, 
{"key1": "value1", "key2": "value8", "key1": "value9"} ]

Теперь мне нужно просмотреть этот словарь, чтобы отформатировать некоторые данные, например:

for datadict in data:  
    for key, value in datadict.items():  
    ...filter the data...

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

Итак, допустим, я хочу создать под-словарь со всеми списками, в которых key1 имеет значение «value1», что для приведенного выше списка даст мне что-то вроде этого:

subdata = [ {"key1": "value1", "key2": "value2", "key1": "value3"},  
{"key1": "value1", "key2": "value8", "key1": "value9"} ]

Ответы [ 5 ]

9 голосов
/ 01 августа 2009

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

Предикат - это функция, которая решает для каждой пары ключ / значение, будет ли ее сокращать словарь в списке. По умолчанию один принимает все. Если ни одна k / v-пара в словаре не совпадает, она отклоняется.

def filter_data(data, predicate=lambda k, v: True):
    for d in data:
         for k, v in d.items():
               if predicate(k, v):
                    yield d


test_data = [{"key1":"value1", "key2":"value2"}, {"key1":"blabla"}, {"key1":"value1", "eh":"uh"}]
list(filter_data(test_data, lambda k, v: k == "key1" and v == "value1"))
# [{'key2': 'value2', 'key1': 'value1'}, {'key1': 'value1', 'eh': 'uh'}]
3 голосов
/ 01 августа 2009

За исключением проблем, уже отмеченных в других комментариях и ответах (несколько одинаковых ключей не могут быть указаны в диктовке и т. Д.), Вот как я это сделаю:

def select_sublist(list_of_dicts, **kwargs):
    return [d for d in list_of_dicts 
            if all(d.get(k)==kwargs[k] for k in kwargs)]

subdata = select_sublist(data, key1='value1')
1 голос
/ 01 августа 2009

Ответ слишком прост, поэтому, я думаю, нам не хватает какой-то информации. В любом случае:

result = []
for datadict in data:
    for key, value in datadict.items():
        thefiltering()

    if datadict.get('matchkey') == 'matchvalue':
        result.append(datadict)

Кроме того, вы "основной словарь" - это не словарь, а список Просто хотел это прояснить.

0 голосов
/ 07 октября 2015

Это старый вопрос, но по какой-то причине нет однострочного синтаксического ответа:

{ k: v for k, v in <SOURCE_DICTIONARY>.iteritems() if <CONDITION> }

Например:

src_dict = { 1: 'a', 2: 'b', 3: 'c', 4: 'd' }
predicate = lambda k, v: k % 2 == 0
filtered_dict = { k: v for k, v in src_dict.iteritems() if predicate(k, v) }

print "Source dictionary:", src_dict
print "Filtered dictionary:", filtered_dict

Будет выдавать следующий вывод:

Source dictionary: {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
Filtered dictionary: {2: 'b', 4: 'd'}
0 голосов
/ 30 августа 2010

Вдохновленный ответом Скурмедала, я разделил это на рекурсивную схему для работы с базой данных вложенных словарей. В этом случае «запись» является вспомогательной в стволе. Предикат определяет, какие записи мы ищем - те, которые соответствуют некоторой паре (ключ, значение), где эти пары могут быть глубоко вложенными.

def filter_dict(the_dict, predicate=lambda k, v: True):
    for k, v in the_dict.iteritems():
        if isinstance(v, dict) and _filter_dict_sub(predicate, v):
            yield k, v

def _filter_dict_sub(predicate, the_dict):
    for k, v in the_dict.iteritems():
        if isinstance(v, dict) and filter_dict_sub(predicate, v):
            return True
        if predicate(k, v):
            return True
    return False

Поскольку это генератор, вам, возможно, потребуется заключить в dict(filter_dict(the_dict)), чтобы получить отфильтрованный словарь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...