python - 比较Python中的字典列表和嵌套列表

标签 python arrays list dictionary

我想获得具有以下结构的两个列表的差异:

first_dict = [{"a": "abcd","b":"defg", "c":["fng","xvg"]}, {"a": "stg","b":"klsm", "c":["xzy"]}]

second_dict = [{"a": "abcd","b":"defg", "c":["fng","xvg"]}]

我尝试按如下方式卡住集合:

i_set = { frozenset(row.items()) for row in first_dict }
a_set = { frozenset(row.items())  for row in second_dict }
result = [dict(i) for i in i_set - a_set]

预期结果:

v = {"a": "stg","b":"klsm", "c":["xzy"]}

因为 "c":[] 是一个列表,我收到以下错误:

TypeError: unhashable type: 'list'

我看过类似的答案herehere但它们不能解决我的问题。

最佳答案

由于您使用了 setfrozenset 我假设您关心效率并且不想要 O(n**2) 算法.

在这种情况下,您不仅需要将字典转换为卡住集,还需要将列表转换为可哈希类。您可以使用元组。

假设您的输入:

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']}]

关于python - 比较Python中的字典列表和嵌套列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56414409/

相关文章:

python - 从 XML 中删除父元素和所有子元素

简单的 Python 索引

python - 从 LocalSystem 服务(通过 CreateProcessAsUser)生成的 GUI 应用程序没有焦点

java - 如何修改某些数组元素而不影响其他元素?

python - 如何从元组列表中提取第 n 个元素

python - 查找网格中周围单元格的最低值

python - 理解python for循环语句中的变量声明

java - 输入、数组和 NextLine

php - PHP中如何将对象转换为特定格式的数组

c# - 主要: not all code paths return a value