6

我有:

tuple1 = token1, token2
tuple2 = token2, token1
for tuple in [tuple1, tuple2]:
    if tuple in dict:
        dict[tuple] += 1
    else:
        dict[tuple] = 1

但是,元组 1 和元组 2 的计数相同。有什么方法可以散列一组 2 个事物以使顺序很重要?

4

3 回答 3

23

散列时考虑顺序:

>>> hash((1,2))
1299869600
>>> hash((2,1))
1499606158

这假设对象本身具有唯一的哈希值。即使他们不这样做,在字典中使用它时仍然可以(只要对象本身不等于他们的__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

请注意,由于哈希冲突,此字典的效率可能低于另一个没有哈希冲突的字典 :)

于 2013-01-17T21:18:41.893 回答
7

它们获得相同计数的原因是您的代码同时显式递增token1,token2token2,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
于 2013-01-17T21:19:04.867 回答
0

好像您已经发布了一个循环体的实例。我是否可以建议您使用 collections.Counter您正在尝试做的事情,这正是您想要的,但在一行中:

counter = (collections.Counter(myListOfTuples) + 
           collections.Counter([j,i for i,j in myListOfTuples]))
于 2013-01-17T21:25:23.180 回答