2016-01-18 4 views
2

У меня есть словарь и вы хотите удалить определенные значения в bad_list из его списка значений и вернуть остаток. Вот код:Извлечение словаря подмножеством значений из другого словаря

d = {1: ['a', 'c', 'd'], 2: ['b'], 5: ['e']} 

bad_list = ['d','e'] 

ad = {k:d[k].remove(i) for k in d.keys() for sublist in d[k] for i in sublist if i in bad_list} 

print 'd =', d 

print 'ad =', ad 

К сожалению, что это делает это изменяет значения в d постоянно, и возвращает None значений в объявлении.

d = {1: ['a', 'c'], 2: ['b'], 5: []} 

ad = {1: None, 5: None} 

Как я могу получить словарь, который выглядит следующим образом:

new_dict = {1: ['a','c'], 2:['b']} 

без зацикливания через? У меня есть гораздо больший словарь для работы, и я бы хотел сделать это наиболее эффективным способом.

+1

Как вы сказали, просто используйте понимание списка. Почему это не работает по вашему делу? Поскольку функция 'remove' удаляет элемент из вашего списка и возвращает' None', и согласно вашему описанию, это именно то, чего вы не хотите, чтобы удалить элемент .... не используйте 'remove' – tglaria

+0

Спасибо за ответ! – Arty

ответ

2

Там нет никакого способа сделать это без цикла:

d = dict((key, [x for x in value if x not in bad_list]) for key, value in d.iteritems()) 

или с фильтром:

d = dict((key, filter(lambda x: x not in bad_list, d[key])) for key in d) 

UPDATE

Чтобы исключить пустые значения:

d = dict((key, list(x)) for key in d for x in [set(d[key]).difference(bad_list)] if x) 
+0

Он, кажется, хочет, чтобы пустой список '5' тоже отфильтровывался. –

+0

upvoted bc * filter * является самым pythonic – rbp

+0

Спасибо, это работает чудесно! – Arty

0

Ну , ты мог просто используйте «понимание списка», этот один лайнер работает, подумал, что я нахожу его уродливым.

ad = {k:v for k,v in {k:[i for i in v if i not in bad_list] for k,v in d.items()}.items() if v} 

Лучше использовать цикл for.

ad2 = dict() 
for k,v in d.items(): 
    _data_ = [item for item in v if item not in bad_list] 
    if _data_: 
     ad2[k]=_data_ 

Выход:

print 'd =', d 
print 'ad =', ad 
print 'ad2=', ad2 

>d = {1: ['a', 'c', 'd'], 2: ['b'], 5: ['e']} 
>ad = {1: ['a', 'c'], 2: ['b']} 
>ad2= {1: ['a', 'c'], 2: ['b']} 
+0

Спасибо! Знаете ли вы, что конструкция ad2 через цикл for принимает одно и то же время, что и однострочная версия, использующая понимание списка? Я хотел держаться подальше от каждого элемента, если это возможно, так как у меня есть гораздо больший словарь для решения. Благодаря! – Arty

+0

Я понятия не имею, вам придется время. – tglaria

+0

Похоже, что цикл немного быстрее: https://repl.it/BfBe. https://repl.it/BfBg – tglaria

0

Следующий код, написанный на Python 3.5, как представляется, сделать в соответствии с просьбой в вашем вопросе. Минимальное изменение должно быть необходимо для работы с Python 2.x. Просто используйте операторы print вместо функций.

d = {1: ['a', 'c', 'd'], 2: ['b'], 5: ['e']} 
bad_list = ['d', 'e'] 
ad = {a: b for a, b in ((a, [c for c in b if c not in bad_list]) for a, b in d.items()) if b} 
print('d =', d) 
print('ad =', ad) 
Смежные вопросы