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

2024-05-12 20:33:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我想得到两个具有以下结构的列表的区别:

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,但它们对我的问题不起作用。你知道吗


Tags: in列表fordictrowfirstsecondabcd
2条回答

既然您使用了setfrozenset,我假设您关心效率而不需要O(n**2)算法。你知道吗

在这种情况下,您不仅需要将字典转换为冻结集,还需要将列表转换为可哈希类。你可以用tuples

假设您的输入:

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

然而,这不会区分元组中的元组和元组列表中的元组。你知道吗


您可以通过将字典包装到自己的hashable类中来解决这个问题(如果您确定字典及其内容在操作过程中没有发生变化)。这样做的好处是,以后不需要将它们转换回来,只需“展开”值即可。你知道吗

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

为什么frozenset?,只需使用:

>>> 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 for i in first_dict if i not in second_dict]
[{'a': 'stg', 'b': 'klsm', 'c': ['xzy']}]
>>> 

或者如果你想要一个单数,改变:

>>> [i for i in first_dict if i not in second_dict]

收件人:

>>> [i for i in first_dict if i not in second_dict][0]

输出:

{'a': 'stg', 'b': 'klsm', 'c': ['xzy']}

相关问题 更多 >