2016-02-02 4 views
2

Рассмотрим следующий по умолчанию ДИКТ:Фильтрация defaultdict на основе значения

data = defaultdict(list) 
data['key1'] = [{'check': '', 'sth1_1':'k1', 'sth1_2':'k2'}] 
data['key2'] = [{'check': '0', 'sth2_1':'k3'}, {'check': 'asd', 'sth2_2':'k4'}, {'check':'1', 'sth2_3':'k5'}] 

и так далее ..

Я хотел бы FILER из data словарей (от data.values ​​()), значение 'check' != '1'

Для данного входа выше я бы ожидать:

defaultdict(<type 'list'>, {'key2': [{'sth2_3': 'k5', 'check': '1'}]) 

До сих пор я получил:

for k, v in data.items(): 
    print "k, v: ", k, v 
    v[:] = [d for d in v if d.get('check') == '1'] 

Но это дает мне выход с нежелательной 'key1': []:

defaultdict(<type 'list'>, {'key2': [{'sth2_3': 'k5', 'check': '1'}], 'key1': []}) 

Что бы лучший вещий способ решить это?

+1

Почему '' key1 ': [] 'нежелательно? Когда 'd.get ('check') == '1'' дает' False', 'v [:]' будет пустым списком. Вы хотите удалить «key1»? –

+0

К сожалению, да, мне нужно, чтобы отфильтрованный dict содержал только значение ключа, отвечающее установленному условию. –

ответ

1

Я думаю, что это достаточно просто:

for k,v in data.items(): 
    filtered_vals = list(filter(lambda i: i['check'] == '1', v) 
    if len(filtered_vals): 
     data[k] = filtered_vals 
    else: 
     del data[k] 

или, если вы с умом :

data = {k:v for k,v in { k:list(filter(lambda i: i['check'] == '1' ,v)) for k, v in data.items()}.items() if len(v)} 
+1

приятное использование фильтра! FWIW, списки python имеют неявное логическое значение. так что вы можете заменить if len (x), если x: когда x - это список –

+1

Да, я это видел, но я решил, что пять символов для дополнительной ясности в отношении того, что мы на самом деле проверяем, были бы хороши для читаемости. – dalanmiller

+0

Наконец-то выяснилось, что у меня будет еще одно правило фильтрации - она ​​разрешила редактирование второй строки вашего решения: 'filter_vals = list (filter (lambda i: i ['check'] == '1' и i [ 'check2'] в check_list, v)) 'работал отлично на данный момент! –

2

Это сделает это на месте. Его можно немного очистить, если вы в порядке сделаете новый словарь.

for key in data.keys(): 
    new_list = [] 
    for val in data[key]: 
     if val['check'] == '1': 
      new_list += [val] 
    if new_list: 
     data[key] = new_list 
    else: 
     del data[key] 

Если вы действительно хотите использовать (вложенные) постижения, это тоже будет работать:

d = {} 
d = {key: [inner_dict for inner_dict in list_of_dicts if inner_dict['check'] == '1'] for key, list_of_dicts in data.iteritems()} 
d = {key: val for key,val in d.iteritems() if val}