繁体   English   中英

排序和比较Dicts Python列表

[英]Sort and Compare List of Dicts Python

我试图找到一种方法来排序和比较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)

这甚至可能吗?

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

>>> 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', '')]

脚注

为了使(key,value)对的列表与其他dicts列表相当, None值必须转换为空字符串。 这允许None值与其他非None值相比较。

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

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

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

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

Out[218]: 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'}]
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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM