2009-07-31 3 views
5

Хорошо, я застрял, нужна помощь здесь и далее ...Фильтрация словарей и создание суб-словарей на основе ключей/значений в Python?

Если у меня есть основной словарь вроде этого:

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... 

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

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

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

«Основной словарь как это» неверен. У вас есть список словарей. –

+0

И словарные ключи уникальны, поэтому вы не можете построить словарь с такими же повторяющимися ключами: {"key1": "value1", "key2": "value2", "key1": "value3"}; результат: {'key2': 'value2', 'key1': 'value3'}. Если вам действительно нужны дубликаты, вам понадобится список, поэтому общая структура будет списком списков или значения словаря должны содержать кортежи или списки. –

ответ

9

Вот не очень красивый способ сделать это. В результате получается генератор, но если вам действительно нужен список, вы можете окружить его вызовом 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'}] 
+2

«Не так красиво»? Не согласен. Это очень мило. –

+0

Спасибо :). Я склоняюсь к мысли, что подобные функции лестничного типа уродливы. – Skurmedel

+1

@Skurmedel: Ваша функция элегантная, и ее легко увидеть, как она работает в простых шагах; это избавляет читателей от необходимости разбирать сложный однострочный вкладыш в их головах. –

1

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

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

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

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

3

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

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') 
0

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

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)) для получения отфильтрованного словаря.

0

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

{ 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'} 
Смежные вопросы