排序和比较Dicts Python列表

时间:2017-12-20 19:36:15

标签: python python-3.x list sorting dictionary

我试图找到一种方法来排序和比较Python 3.6中的两个字典列表。我最终只希望list_dict_alist_dict_b==进行比较并评估为True

以下是数据的样子:

list_dict_a = [
{'expiration_date': None, 'identifier_country': None, 'identifier_number': 'Male', 'identifier_type': 'Gender', 'issue_date': None},
{'expiration_date': None, 'identifier_country': 'VE', 'identifier_number': '1234567', 'identifier_type': 'Foo No.', 'issue_date': None}]

list_dict_b = [
{'identifier_country': 'VE', 'expiration_date': None, 'identifier_type': 'Foo No.', 'issue_date': None, 'identifier_number': '1234567'},
{'identifier_country': None, 'expiration_date': None, 'identifier_type': 'Gender', 'issue_date': None, 'identifier_number': 'Male'}]

数据是相同的,但它有不同的顺序(我对初始订单没有任何控制权)。

当我尝试比较它们时,我在做这样的事情时会得到一个假值: print("does this match anything",list_dict_a == list_dict_b)

这甚至可以吗?

3 个答案:

答案 0 :(得分:2)

您可以在比较两个列表之前对它们进行排序,并比较排序后的结果:

>>> list_dict_a = [
        {'expiration_date': None, 'identifier_country': None, 'identifier_number': 'Male', 'identifier_type': 'Gender', 'issue_date': None},
        {'expiration_date': None, 'identifier_country': 'VE', 'identifier_number': '1234567', 'identifier_type': 'Foo No.', 'issue_date': None}]

>>> list_dict_b = [
        {'identifier_country': 'VE', 'expiration_date': None, 'identifier_type': 'Foo No.', 'issue_date': None, 'identifier_number': '1234567'},
        {'identifier_country': None, 'expiration_date': None, 'identifier_type': 'Gender', 'issue_date': None, 'identifier_number': 'Male'}]

>>> list_dict_a == list_dict_b
False
>>> def key_func(d):
        items = ((k, v if v is not None else '') for k, v in d.items())
        return sorted(items)
>>> sorted(list_dict_a, key=key_func) == sorted(list_dict_b, key=key_func)
True

每个列表中的dicts顺序无关紧要。

需要传递key函数,因为dicts是不可订购的,因此我们需要告诉排序函数在比较它们时对每对dict对象使用什么键。每个字典的键只是其(键,值)对的排序列表。

key函数为每个dict计算一个键,如下所示:

>>> dict_a0 = list_dict_a[0]
>>> key_func(dict_a0)
[('expiration_date', ''), ('identifier_country', ''), ('identifier_number', 'Male'), ('identifier_type', 'Gender'), ('issue_date', '')]

<强>脚注

为了使这个(键,值)对的列表与其他词组相比较,列表,None值必须转换为空字符串。这允许None值与其他非None值相比。

上述解决方案中的基本假设是,您的案例中的所有字典值都是字符串或None,并且&#34;空&#34;值始终表示为None(而不是例如空字符串)。如果不是这种情况,则必须相应地调整key_func(),以确保结果列表始终与数据中预期的任何字典值相互比较。

此外,对于大型dicts,这个关键功能可能并不理想,因为密钥对的比较会太慢。因此,最好为每个字典计算一个唯一的哈希值(但对于比较相等的字母,则使用相同的哈希值)。

答案 1 :(得分:0)

您还可以检查list_dict_a中的每个字典是否在list_dict_b

all([dict_a in list_dict_b for dict_a in list_dict_a])

Out[218]: True

答案 2 :(得分:0)

你可以试试这个:

list_dict_a = [
{'expiration_date': None, 'identifier_country': None, 'identifier_number': 'Male', 'identifier_type': 'Gender', 'issue_date': None},
{'expiration_date': None, 'identifier_country': 'VE', 'identifier_number':  '1234567', 'identifier_type': 'Foo No.', 'issue_date': None}]

list_dict_b = [
{'identifier_country': 'VE', 'expiration_date': None, 'identifier_type': 'Foo No.', 'issue_date': None, 'identifier_number': '1234567'},
{'identifier_country': None, 'expiration_date': None, 'identifier_type': 'Gender', 'issue_date': None, 'identifier_number': 'Male'}]
new_list = sorted(list_dict_a, key=lambda x:x['identifier_country'] is not None, reverse=True)
print(new_list == list_dict_b)

输出:

True

如果您最初不知道密钥,可以试试这个:

new_list = sorted(list_dict_a, key=lambda x:x.get('identifier_country', None) is not None, reverse=True)