Вычитание словарей (фильтрация)

Есть 2 словаря

dic1 = {
    'NAME': 'JACK',
    'AGE': '20',
    'ID': '10',
    'FK_ID': '35',
    'CONST_ID': '141',
    'CODE_SK': 'LAST'
}

dic2 = {
'CODE': 'ID, FK_ID',
'CONST': 'CONST_ID'
}

Нужно из первого словаря (dic1) исключить пары ключ/значение, которые есть во втором словаре как значение (dic2), при этом значение во втором словаре могут быть через запятую, которые в первом являются ключом. Должно получится так:

dic3 = {
    'NAME': 'JACK',
    'AGE': '20',
    'CODE_SK': 'LAST'
}

Пробовал словарь преобразовать в set и вычитать, но такой метод не сработал.


Ответы (2 шт):

Автор решения: nomnoms12

Предлагаю сначала сгенерировать список ключей, которые должны быть удалены из словаря. А потом отфильтровать ключи словаря по условию.

Для получения списка ключей можно проитерировать значения словаря и разделить каждое по запятой с помощью метода split. Лишние пробельные символы можно удалить с помощью strip.

Пример:

# ['ID', 'FK_ID', 'CONST_ID']
keys = [subkey.strip() for value in dic2.values() for subkey in value.split(',')]

result = {key: value for key, value in dic1.items() if key not in keys}
print(result)

stdout:

{'NAME': 'JACK', 'AGE': '20', 'CODE_SK': 'LAST'}
→ Ссылка
Автор решения: SergFSM

Еще это можно сделать через удаление ключей из словаря (или его копии, если оригинал надо сохранить):

for v in dic2.values():
    for k in v.split(','):
        del dic1[k.strip()]

Правда если в dic2 будут ключи, которых нет в dic1 код выдаст ошибку. Это можно обойти если вместо del использовать pop. То есть примерно так:

dic2 = {'CODE': 'ID, FK_ID',
        'CONST': 'CONST_ID, test_key'}

[dic1.pop(k.strip(), None) for v in dic2.values() for k in v.split(',')]

print(dic1)  # {'NAME': 'JACK', 'AGE': '20', 'CODE_SK': 'LAST'}

Такой способ может быть оправдан если dic1 содержит большое количество ключей и вместо того, чтобы проверять в цикле каждый ключ можно пройти циклом по dic2 и удалить совпадения.

→ Ссылка