Python 哈希位数组?计数
出于某种原因,dict不能有一个非重复的密钥,即bitarray() 例: {bitarray('11011'):1,bitarray('11011'):1,bitarray('11011'):1,bitarray('01111'):1,bitarray('11110'):1,bitarray('01111'):1,bitarray('11110'):1,bitarray('11110'):1,bitarray('11110'):1} 您可以清楚地看到,副本存储为不同的键(即前两个元素)!!这很奇怪。原因可能是什么。 我的目标是简单地计算一个位模式出现的次数,当然Dict非常适合这样做,但是出于某种原因,bitarray()似乎对哈希算法是不透明的。 顺便提一下我必须使用bitarray(),因为我需要10000位+模式 关于计算位模式发生率的有效方法的任何其他想法 我解决了它:Python 哈希位数组?计数,python,dictionary,counting,bitarray,Python,Dictionary,Counting,Bitarray,出于某种原因,dict不能有一个非重复的密钥,即bitarray() 例: {bitarray('11011'):1,bitarray('11011'):1,bitarray('11011'):1,bitarray('01111'):1,bitarray('11110'):1,bitarray('01111'):1,bitarray('11110'):1,bitarray('11110'):1,bitarray('11110'):1} 您可以清楚地看到,副本存储为不同的键(即前两个元素)!!这很
desc = bitarray(res).to01()
if desc in data : data[desc] += 1
else : data[desc] = 1
天哪,我错过了perl无意义的自动激活:)这个答案解决了您关于重复字典键的第一个困惑,我假设您指的是模块中的
bitarray()
,*我自己没有使用过这个模块
在上面的示例中,您实际上并没有得到重复的字典键,您可能会以这种方式看到它们,但它们仅在肉眼下是重复的,例如:
>>> class X:
... def __repr__(self):
... return '"X obj"'
...
>>> x1 = X()
>>> x2 = X()
>>> d = {x1:1, x2:2}
>>> d
{"X obj": 2, "X obj": 1}
但是x1
并不完全等于x2
,因此它们不是重复的,它们是类X
的不同对象:
>>> x1 == x2
False
>>> #same as
... id(x1) == id(x2)
False
>>> #same as
...x1 is x2
False
此外,由于X
类定义了返回其对象的字符串表示形式的\uuuu repr\uuuu
,因此您可能会认为dictionaryd
具有重复的键,同样没有重复的键,也没有类型为str
的键;值1的键是X
对象,值2的键是X
的另一个对象——实际上是两个不同的对象,它们的类的\uuuuu repr\uuu
方法返回一个字符串表示:
>>> # keys are instance of X not strings
... d
{"X obj": 2, "X obj": 1}
>>> d["X obj"]
KeyError: 'X obj'
>>>[x1]
1
>>>[x2]
2
直到
位数组0.8.1
(或更高版本),我认为它不满足哈希不变属性
要解决这个问题,您应该将位数组转换为byte
格式,如下所示
>>> from bitarray import bitarray
>>> l = [bitarray('11111'), bitarray('11111'), bitarray('11010'), bitarray('11110'), bitarray('11111'), bitarray('11010')]
>>> for x in l: ht[x.tobytes()] = 0
...
>>> for x in l: ht[x.tobytes()] += 1
...
>>> ht
{'\xf8': 3, '\xf0': 1, '\xd0': 2}
请记住,您可以使用命令frombytes(byte)
从byte
格式中获取bitarray
。不过,在这种情况下,您必须明确跟踪bitarray
的大小,因为它将返回大小为8倍的bitarray
如果要在字典中同时保留位数组
:
>>> from bitarray import bitarray
>>> l = [bitarray('11111'), bitarray('11111'), bitarray('11010'), bitarray('11110'), bitarray('11111'), bitarray('11010')]
>>> ht = {}
>>> for x in l: ht[x.tobytes()] = (0, x)
...
>>> for x in l:
... old_count = ht[x.tobytes()][0]
... ht[x.tobytes()] = (old_count+1, x)
...
>>> ht
{'\xf8': (3, bitarray('11111')), '\xf0': (1, bitarray('11110')), '\xd0': (2, bitarray('11010'))}
>>> for x,y in ht.iteritems(): print(y)
...
(3, bitarray('11111'))
(1, bitarray('11110'))
(2, bitarray('11010'))
.tobytes()
将生成一个更紧凑的对象,适合用作字典键。在这种情况下,collections.Counter
比原始字典更容易使用。不能有意义地将位数组用作dict键。即使尝试也会引发TypeError,但是该类有一个bug,它继承了默认的基于身份的哈希,而不是使用PyHash。
>>> from bitarray import bitarray
>>> l = [bitarray('11111'), bitarray('11111'), bitarray('11010'), bitarray('11110'), bitarray('11111'), bitarray('11010')]
>>> ht = {}
>>> for x in l: ht[x.tobytes()] = (0, x)
...
>>> for x in l:
... old_count = ht[x.tobytes()][0]
... ht[x.tobytes()] = (old_count+1, x)
...
>>> ht
{'\xf8': (3, bitarray('11111')), '\xf0': (1, bitarray('11110')), '\xd0': (2, bitarray('11010'))}
>>> for x,y in ht.iteritems(): print(y)
...
(3, bitarray('11111'))
(1, bitarray('11110'))
(2, bitarray('11010'))