Python 如何在没有顺序的情况下使用dict断言两个列表?
各位。我最近从Python2切换到3.5.1,有一个断言函数,我无法重写Python 如何在没有顺序的情况下使用dict断言两个列表?,python,unit-testing,python-3.x,Python,Unit Testing,Python 3.x,各位。我最近从Python2切换到3.5.1,有一个断言函数,我无法重写 def assertEqualUnordered(self, data1, data2): """ compare that data are similar i.e.: [d1, d2] == [d2, d1] or {'a': [d1, d2]} == {'a': [d2, d1]} or [{'a': [d1, d2]}, {'b': [d3, d4]}
def assertEqualUnordered(self, data1, data2):
"""
compare that data are similar
i.e.:
[d1, d2] == [d2, d1]
or
{'a': [d1, d2]} == {'a': [d2, d1]}
or
[{'a': [d1, d2]}, {'b': [d3, d4]}] == [{'b': [d4, d3]}, {'a': [d2, d1]}]
"""
if isinstance(data1, list) or isinstance(data1, tuple):
self.assertEqual(len(data1), len(data2))
for d1, d2 in zip(sorted(data1), sorted(data2)):
self.assertEqualUnordered(d1, d2)
elif isinstance(data1, dict):
data1_keys = sorted(data1.keys())
data2_keys = sorted(data2.keys())
self.assertListEqual(data1_keys, data2_keys)
for key in data1_keys:
self.assertEqualUnordered(data1[key], data2[key])
else:
self.assertEqual(data1, data2)
一般来说,此代码正常工作,但如果d1和d2是DICT,则我得到:
TypeError:无序类型:dict()
我如何重写它才能在py3k中工作
编辑1:
简化代码示例:
def assertEqualUnordered(data1, data2):
assert len(data1) == len(data2)
for d1, d2 in zip(sorted(data1), sorted(data2)):
assert d1 == d2
data1 = [{'a': 'a'}, {'b': 'b'}]
data2 = [{'b': 'b'}, {'a': 'a'}]
assertEqualUnordered(data1, data2)
我不确定这是否是最简单的方法,但您可以通过恢复Python3删除的
cmp
函数来实现排序。大致如下:
def cmp(lhs, rhs):
try:
if lhs == rhs:
return 0
elif lhs < rhs:
return -1
else:
return 1
except TypeError:
if isinstance(lhs, dict) and isinstance(rhs, dict):
return dict_cmp(lhs, rhs)
raise
def cmp(左侧、右侧):
尝试:
如果lhs==rhs:
返回0
elif lhs
有关dict\u cmp
的实现,请参阅
一旦有了cmp
函数,就可以进行排序(data1,key=functools.cmp_to_key(cmp))
这仍然不完整,因为我还没有尝试讨论混合类型比较,例如,如果您将[{'a':'b'},['a']]
作为对象之一传入,就会出现混合类型比较。但希望我已经提供了一个前进的方向
另一种选择是回到O(n^2)
算法,这实际上与Python3的观点一致,即字典没有顺序。不要对列表进行排序,然后比较它们是否相等,而是依次选择左侧的每个项目,并在右侧搜索与其相等的项目(删除以确保两侧的计数相同,因为您不希望错误地声称[x,x,y]
等于[x,y,y]
)
顺便说一句,答案并不需要,但我注意到您当前的代码会说
['a','b']
与{'a':'foo','b':'bar'}
无序相等,但前提是列表在左侧,词典在右侧。如果您以另一种方式传递它们,那么当代码试图调用列表上的keys()
时,您会得到一个异常。这可能需要寻址,具体取决于您计划传入的内容;-) 你能不能简化一下,更深入地了解你所看到的失败?我假设这与keys()返回视图而不是列表有关。另外,您可以包含完整的堆栈跟踪吗?显示引发异常的代码:此代码不使用@jgritty simplify代码example@SteveJessop但是有一个分类code@vanadium23:是的,如果您显示了异常堆栈跟踪,那么我们可以看到异常是否来自对排序的调用,如果是,则是哪一个:-)我认为您添加的示例涵盖了它,谢谢,因为现在只有一个地方会出错!