不可哈希对象的无序集合?
我有一个字典,其中一些值是不可哈希的。这意味着我不能直接用它们来比较两个无序的组,以确保它们包含相同的元素。我不能用列表,因为列表的比较会考虑顺序,但集合也不行,因为字典本身是不可哈希的。我查了一下Python的文档,发现唯一看起来有用的就是字典的视图,在某些情况下它是可哈希的,但在这种情况下也没用,因为其中一个值是一个包含列表的对象,这样字典的视图也就不可哈希了。
有没有什么标准的容器可以处理这种情况,还是说我应该直接用列表,然后逐个循环检查两个列表中的每个元素,确保另一个列表中有相同的元素呢?
2 个回答
我觉得最简单的方法就是用列表。
group_1 = my_dict_1.values()
group_2 = my_dict_2.values()
你的比较可能不会像考虑顺序或值可以哈希那样简单,但下面的方法应该可以用:
def contain_the_same(group_1, group_2):
for item in group_1:
if item not in group_2:
return False
else:
group_2.pop(group_2.index(item))
if len(group_2) != 0:
return False
return True
这个方法可以很好地处理那些不能哈希的对象:
>>> contain_the_same([1,2,3], [1,2,3])
True
>>> contain_the_same([1,2,3], [1,2,3,4])
False
>>> contain_the_same([1,2,[3,2,1]], [1,2,[3,2,1]])
True
>>> contain_the_same([5,1,2,[3,2,1,[1]]], [1,[3,2,1,[1]],2,5])
True
需要注意的是:如果一个列表里有重复的元素,而另一个列表没有,这个方法会返回假。这种情况下,如果你想允许重复元素,就需要做一些修改。
补充:其实还有更简单的方法:
sorted(my_dict_1.values()) == sorted(my_dict_1.values())
看起来这个方法的速度是我之前的 contain_the_same
函数的两倍:
>>> timeit("contain_the_same([5,1,2,[3,2,1,[1]]], [1,[3,2,1,[1]],2,5])",
"from __main__ import contain_the_same", number=10000)/10000
8.868489032757054e-06
>>>timeit("sorted([5,1,2,[3,2,1,[1]]]) == sorted([1,[3,2,1,[1]],2,5])",
number=10000)/10000
4.928951884845034e-06
不过,这个方法在处理允许重复元素的情况下就没有那么简单了。
当没有重复项时,通常的选择有:
如果元素可以被哈希(简单来说,就是可以用来快速查找的):可以用
set(a) == set(b)
来比较。如果元素可以排序:可以用
sorted(a) == sorted(b)
来比较。如果你只关心是否相等:可以用
len(a) == len(b) and all(x in b for x in a)
来比较。
如果有重复项,并且重复的数量很重要,选择就变成:
如果元素可以被哈希:可以用
Counter(a) == Counter(b)
来比较,这样可以统计每个元素出现的次数。如果元素可以排序:同样可以用
sorted(a) == sorted(b)
来比较。如果你只关心是否相等:可以用
len(a) == len(b) and all(a.count(x) == b.count(x) for x in a)
来比较,这样会检查每个元素在两个列表中出现的次数是否相同。