我正在尝试排序和比较包含字典列表和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
进行比较,以评估True
。
我试图遍历字典,将项目发送到Pandas并将dict
设置为ordered_dict
,但这似乎不起作用。我不确定最好的方法。
# Loop over data, and conver the list of dicts to data frame for sorting,
# then take the data, once sorted, and put it back into list of dicts
for key, val in dict_A.items():
if type(val) is list:
val.sort(key=lambda x: x if isinstance(x, str) else "")
dataframe = pd.DataFrame(val, index=range(len(val)))
dataframe.sort_values(by=dataframe.columns[0])
new_val = [OrderedDict(row) for i, row in dataframe.iterrows()]
dict_A.update({key: new_val})
也许更好的方法是将字典设置为列表,并以这种方式进行比较?
因此,如果您只有列表和词典,则可以在每个列表和词典上调用自定义相等的方法。例如,
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
这比以前好多了。
将您的词典转换为数据结构,即真实的类。
对于此类,如果您希望能够对每个对象进行排序,请为每个对象重载__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更改为现在使用上述类。
现在,您可以根据需要进行排序和比较,而无需立即处理所有属性。
如果在这一点上不明显,你现在的dict将是一个ApiDto
,它有一个name
字段,addresses
字段是Address
列表,ids
字段是Id
列表,最后是dob
字段。
当您为qazxsw poi重载qazxsw poi和qazxsw poi方法时,您将对所有类执行相同操作,这将允许您对对象进行排序并最终将它们相互比较。
此外,如果你需要将对象转换回dict,你可以调用__cmp__
属性给你这个