哈希比特阵?数数

时间:2017-05-18 21:03:12

标签: python dictionary counting bitarray

似乎由于某种原因,dict不能有一个非重复的键,这是bitarray() 例如:

data = {}
for _ in xrange(10):
   ba = ...generate repeatable bitarrays ...
   data[ba] = 1

print ba
  

{bitarray(' 11011'):1,bitarray(' 11011'):1,bitarray(' 11011'):1,bitarray(&# 39; 01111'):1,bitarray(' 11110'):1,bitarray(' 11110'):1,bitarray(' 01111'): 1,bitarray(' 01111'):1,bitarray(' 11110'):1,bitarray(' 11110'):1}

您可以清楚地看到副本存储为不同的键(例如前两个元素)!!这很奇怪。可能是什么原因。 我的目标只是计算一个模式显示的次数,当然Dict是完美的,但似乎bitarray()由于某种原因对散列算法是不透明的。 顺便说一句..我必须使用bitarray(),因为我做10000比特+模式。

计算位模式发生的有效方法的任何其他想法..

3 个答案:

答案 0 :(得分:1)

这个答案解决了你对重复字典键的第一次困惑,我假设你是指bitarray模块中的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类定义__repr__返回其对象的字符串表示形式,您会认为字典d具有重复键,同样没有重复键也没有键类型str;值1的键是X对象,值2的键是X的另一个对象 - 实际上是两个不同的对象,它们的类__repr__方法返回一个字符串表示:

>>> # keys are instance of X not strings
... d
{"X obj": 2, "X obj": 1}    
>>> d["X obj"]
KeyError: 'X obj'
>>>[x1]
1
>>>[x2]
2

答案 1 :(得分:1)

直到BitArray 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}

请记住,您可以使用bitarray命令从byte格式取回frombytes(byte)。但是,在这种情况下,您必须明确跟踪bitarray的大小,因为它将返回大小为8的bitarray

如果您想将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'))

答案 2 :(得分:-1)

我解决了它:

desc = bitarray(res).to01()
if desc in data : data[desc] += 1
else : data[desc] = 1

gosh我想念perl no-unsense autovivification :)