Поскольку вы использовали set
и frozenset
, я полагаю, что вы заботитесь об эффективности и не хотите O(n**2)
алгоритм.
В этом случае вам не нужно просто преобразовывать словари вFrozensets, но также конвертировать списки в класс hashable.Вы можете использовать tuple
с.
Предполагая, что ваши входные данные:
first_dict = [{"a": "abcd","b":"defg", "c":["fng","xvg"]}, {"a": "stg","b":"klsm", "c":["xzy"]}]
second_dict = [{"a": "abcd","b":"defg", "c":["fng","xvg"]}]
Вы можете использовать:
def convert(dictionary):
return frozenset((key, tuple(value) if isinstance(value, list) else value) for key, value in dictionary.items())
def convert_back(frozset):
return dict((key, list(value) if isinstance(value, tuple) else value) for key, value in frozset)
i_set = { convert(row) for row in first_dict }
a_set = { convert(row) for row in second_dict }
result = [convert_back(i) for i in i_set - a_set]
Тогда результат будет:
[{'a': 'stg', 'c': ['xzy'], 'b': 'klsm'}]
Однако это не будет различать кортежи, которые были кортежами в оригинале, и кортежи, которые были списками в оригинале.
Вы можете решить это (если вы уверены, чтословарь и его содержимое не видоизменяются во время операций), оборачивая словари в свой собственный класс.Преимущество в том, что вам не нужно конвертировать их потом, вы можете просто «развернуть» значение.
class HashableDictionaryWithListValues:
def __init__(self, dictionary):
converted = frozenset((key, tuple(value) if isinstance(value, list) else value) for key, value in dictionary.items())
self._hash = hash(converted)
self._converted = converted
self.dictionary = dictionary
def __hash__(self):
return self._hash
def __eq__(self, other):
return self._converted == other._converted
i_set = { HashableDictionaryWithListValues(row) for row in first_dict }
a_set = { HashableDictionaryWithListValues(row) for row in second_dict }
result = [i.dictionary for i in i_set - a_set]
Результат будет:
[{'a': 'stg', 'b': 'klsm', 'c': ['xzy']}]
Хотя вы также можете избежать всего преобразования / переноса и использовать O(n**2)
подход:
def difference(first, second):
for item in first:
if item not in second:
yield item
list(difference(first_dict, second_dict))
, который также дает ожидаемый результат:
[{'a': 'stg', 'b': 'klsm', 'c': ['xzy']}]