У меня есть два словаря, которые имеют следующую структуру:
a = {'joe': [24,32,422], 'bob': [1,42,32,24], 'jack':[0,3,222]}
b = {'joe': [24], 'bob': [1,42,32]}
Я хотел бы получить разницу между этими двумя словарями, которая в этом случае будет выглядеть так:
{'joe': [32,422], 'bob': [24], 'jack':[0,3,222]}
Я знаю, что я мог бы сделать это с грязной петлей, но я хотел бы знать, как я могу добиться этого чистым, питонским способом?
Я попробовал: a.items() - b.items()
Но я получаю следующую ошибку: unsupported operand type(s) for -: 'dict_values' and 'dict_values'
Спасибо за вашу помощь
3 ответа
Предполагая, что ни в одном из ваших списков не будет повторяющихся записей, вы можете делать то, что вы хотите, с set
, но не со списками:
>>> a = {'joe': [24,32,422], 'bob': [1,42,32,24], 'jack':[0,3,222]}
>>> b = {'joe': [24], 'bob': [1,42,32]}
>>> {key: list(set(a[key])- set(b.get(key,[]))) for key in a}
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
Обратите внимание на две вещи:
- Я преобразовываю набор обратно в список, когда я устанавливаю его как значение
- Я использую
b.get
вместоb[key]
для обработки, если ключ не существует вb
, но существует вa
РЕДАКТИРОВАТЬ - используя цикл for:
Я понял, что понимание может быть не столь очевидным, так что это эквивалентный фрагмент кода с использованием цикла for:
>>> c = {}
>>> for key in a:
c[key] = list(set(a[key]) - set(b.get(key,[])))
>>> c
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
РЕДАКТИРОВАТЬ - потерять второй сет:
Как упоминал Падрейк Каннингем в комментариях (как он часто делает, благословляет его душу), вы можете использовать set.difference
, чтобы избежать явного приведения вашего второго списка к набору:
>>> c = {}
>>> for key in a:
c[key] = list(set(a[key]).difference(b.get(key,[])))
>>> c
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
Или с пониманием списка:
>>> {key: list(set(a[key]).difference(b.get(key,[]))) for key in a}
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
Или если вы хотите рассматривать set.difference
как метод класса вместо метода экземпляра:
>>> {key: list(set.difference(set(a[key]),b.get(key,[]))) for key in a}
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
Хотя я нахожу это немного неуклюжим, и мне это не очень нравится.
Другой способ - использование встроенного метода filter
:
>>> a = {'joe': [24,32,422], 'bob': [1,42,32,24], 'jack':[0,3,222]}
>>> b = {'joe': [24], 'bob': [1,42,32]}
>>> {key:filter(lambda s: s not in b.get(key,[]), a[key]) for key in a}
{'bob': [24], 'joe': [32, 422], 'jack': [0, 3, 222]}
Согласно Padraic Cunningham
комментариям:
В Python 3 filter
возвращает generator
, поэтому вам нужно преобразовать его в список следующим образом:
{key:list(filter(lambda s: s not in b.get(key,[]), a[key])) for key in a}
Вам нужно использовать наборы:
diff = {}
for key in a:
diff[key] = list(set(a[key]) - set(b.get(key, [])))
print diff
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.