Python排序和比较嵌套字典

时间:2017-12-20 20:55:38

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

我正在尝试排序和比较包含compute MFQAPsum=sum(!MyVars). 中词典和其他数据列表的词典。我不确定比较两者的最佳方法。两个词典中的数据是相同的,但我无法控制它们的给定顺序。数据如下所示:

Python 3.6

我正在尝试与dict_A = { 'addresses': [ {'address': 'Tribal Land', 'address_country': 'AB', 'city': None, 'postal_code': None, 'state': 'GY'}, {'address': 'Userland', 'address_country': 'ND', 'city': None, 'postal_code': None, 'state': 'KY'}], 'name': 'FooBar', 'dob': None, 'ids':[ {'date': None, 'country': None, 'number': 'Male', 'type': 'Gender', 'location': 'USA'}, {'date': None, 'country': 'VE', 'number': '1234567', 'type': 'Foo No.', 'location': 'USA'}] } dict_B = { 'addresses': [ {'address': 'Userland', 'address_country': 'ND', 'city': None, 'postal_code': None, 'state': 'KY'}, {'address': 'Tribal Land', 'address_country': 'AB', 'city': None, 'postal_code': None, 'state': 'GY'}], 'dob': None, 'id':[ {'country': 'VE', 'date': None, 'type': 'Foo No.', 'location': 'USA', 'number': '1234567'}, {'country': None, 'date': None, 'type': 'Gender', 'location': 'USA', 'number': 'Male'}], 'name': 'FooBar' } 评估dict_A == dict_B进行比较。

我试图遍历字典,将项目发送到Pandas并将True设置为dict,但这似乎不起作用。我不确定最好的方法。

ordered_dict

也许更好的方法是将字典设置为列表,并以这种方式进行比较?

2 个答案:

答案 0 :(得分:1)

因此,如果您拥有列表和词典,则可以在每个列表和词典上调用自定义相等的方法。例如,

def list_equal(l1, l2):
    if type(l1[0]) is dict:
        if len(l1) != len(l2):
            return False
        for i in range(len(l1)):
            if not l1.count(l1[i]) == l2.count(l1[i]):
                 return False
        return True
    return sorted(l1) == sorted(l2)

然后

def structures_equal(s1, s2):
    if not sorted(list(set(s1.keys()))) == sorted(list(set(s2.keys()))):
        return False
    for key in s1:
        if type(s1[key]) is list:
            if not type(s2[key]) is list:
                return False
            elif not list_equal(s1[key], s2[key]):
                return False
        elif not s1[key] == s2[key]:
            return False
        return True

现在列表比较在O(n ^ 2)中运行,因为它计算每行的实例。如果从同一数据源获取这些行,那么为每个行提取唯一ID也很有用。然后,时间变得明显更快,因为我们只比较每个列表中的UIDS及其计数。如果你能把它作为UIDS的字典和分配的行的实例数,那就更好了。例如

[{'address': 'address0', 'foo': 'bar0', 'uid': 0},
 {'address': 'address1', 'foo': 'bar1', 'uid': 1},
 {'address': 'address2', 'foo': 'bar2', 'uid': 2},
 {'address': 'address3', 'foo': 'bar3', 'uid': 3},
 {'address': 'address4', 'foo': 'bar4', 'uid': 4},
 {'address': 'address0', 'foo': 'bar0', 'uid': 0},
 {'address': 'address1', 'foo': 'bar1', 'uid': 1},
 {'address': 'address2', 'foo': 'bar2', 'uid': 2}]

成为

{0: [{'address': 'address0', 'foo': 'bar0', 'uid': 0},
     {'address': 'address0', 'foo': 'bar0', 'uid': 0}],
 1: [{'address': 'address1', 'foo': 'bar1', 'uid': 1},
     {'address': 'address1', 'foo': 'bar1', 'uid': 1}],
 2: [{'address': 'address2', 'foo': 'bar2', 'uid': 2},
     {'address': 'address2', 'foo': 'bar2', 'uid': 2}],
 3: [{'address': 'address3', 'foo': 'bar3', 'uid': 3}],
 4: [{'address': 'address4', 'foo': 'bar4', 'uid': 4}]}

此算法将是

def list_converted_to_dict_equal(d1, d2):
    for key in d1:
        if key not in d2 or len(d1[key]) != len(d2[key]):
            return False
    return True

哪个比以前好多了。

答案 1 :(得分:1)

将您的词典转换为数据结构,即真实的类。

对于这个类,如果你想对它们进行排序,请为每个对象重载__cmp__方法。

如果您希望能够判断两个对象是否相等,则重载__eq__

class ApiDto(object):
    def __cmp__ (self, other):
        pass
    def __eq__ (self, other):
        pass

class Address(object):
    def __cmp__ (self, other):
        pass
    def __eq__ (self, other):
        pass

class Id(object):
    def __cmp__ (self, other):
        pass
    def __eq__ (self, other):
        pass

将dicts更改为现在使用上述类。

现在您可以根据需要进行排序和比较,而无需立即处理所有属性。

如果此时不明显,您拥有的词典现在将是ApiDto,其中name字段,addresses字段是{{1}的列表}},Address字段,是ids的列表,最后是Id字段。

当您为dob重载__cmp____eq__方法时,您将对所有类执行相同操作,这将允许您对对象进行排序,并最终将它们与每个类进行比较其他

此外,如果您需要将对象转换回dict,可以调用ApiDto属性来为此提供