在 Python 中散列一个元组,其中顺序很重要?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14388306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hashing a tuple in Python where order matters?
提问by Shazam
I have:
我有:
tuple1 = token1, token2
tuple2 = token2, token1
for tuple in [tuple1, tuple2]:
if tuple in dict:
dict[tuple] += 1
else:
dict[tuple] = 1
However, both tuple 1 and tuple2 are getting the same counts. What is a way to hash a group of 2 things such that order matters?
但是,元组 1 和元组 2 的计数相同。有什么方法可以散列一组 2 件事,以便顺序很重要?
采纳答案by mgilson
Order is taken into account when hashing:
散列时考虑顺序:
>>> hash((1,2))
1299869600
>>> hash((2,1))
1499606158
This assumes that the objects themselves have unique hashes. Even if they don't, you could still be OK when using it in a dictionary (as long as the objects themselves aren't equal as defined by their __eq__method):
这假设对象本身具有唯一的哈希值。即使他们不这样做,在字典中使用它时您仍然可以(只要对象本身与其__eq__方法定义的不相等):
>>> t1 = 'a',hash('a')
>>> [hash(x) for x in t1] #both elements in the tuple have same hash value since `int` hash to themselves in cpython
[-468864544, -468864544]
>>> t2 = hash('a'),'a'
>>> hash(t1)
1486610051
>>> hash(t2)
1486610051
>>> d = {t1:1,t2:2} #This is OK. dict's don't fail when there is a hash collision
>>> d
{('a', -468864544): 1, (-468864544, 'a'): 2}
>>> d[t1]+=7
>>> d[t1]
8
>>> d[t1]+=7
>>> d[t1]
15
>>> d[t2] #didn't touch d[t2] as expected.
2
Note that due to hash collisions, this dict is likely to be less efficient than another dict where there aren't hash collisions :)
请注意,由于哈希冲突,此 dict 的效率可能低于另一个没有哈希冲突的 dict :)
回答by NPE
The reason they are getting the same count is that your code explicitly increments both token1,token2and token2,token1counts at the same time. If you don't, the counts won't stay in lockstep:
它们获得相同计数的原因是您的代码显式地同时增加token1,token2和token2,token1计数。如果不这样做,计数将不会保持同步:
In [16]: import collections
In [17]: d = collections.defaultdict(int)
In [18]: d[1,2] += 1
In [19]: d[1,2]
Out[19]: 1
In [20]: d[2,1]
Out[20]: 0
回答by inspectorG4dget
It seems like you have posted one instance of the body of a loop. Might I suggest that you use collections.Counterfor what you are trying to do, which does exactly what you want, but in one line:
看起来您已经发布了一个循环体的实例。我是否可以建议您将其 collections.Counter用于您想要做的事情,这正是您想要的,但在一行中:
counter = (collections.Counter(myListOfTuples) +
collections.Counter([j,i for i,j in myListOfTuples]))

