在Python中提高超大字典的性能
我发现,如果我在开头初始化一个空字典,然后在for循环中添加元素到字典中(大约110,000个键,每个键的值是一个列表,循环中也增加),速度降低为for循环去。
我怀疑问题是,字典在初始化时并不知道密钥的数量,而且它并没有做一些非常聪明的事情,所以也许存储冲突变得相当频繁,并且速度变慢了。
如果我知道键的数量,确切地说是那些键,是否有任何方式在Python中使字典(或哈希表)更有效地工作? 我隐约记得,如果你知道密钥,你可以巧妙地devise哈希函数(完美哈希?),并预先分配空间。
如果我知道键的数量,确切地说是那些键,是否有任何方式在Python中使字典(或哈希表)更有效地工作? 我隐约记得,如果你知道密钥,你可以巧妙地devise哈希函数(完美哈希?),并预先分配空间。
Python并没有公开一个预先大小的选项来加速字典的“成长阶段”,也没有提供任何直接控制字典中“放置”的选项。
也就是说,如果提前知道密钥,可以将它们存储在一个集合中,并使用dict.fromkeys()从集合中构build字典。 该类方法已经过优化,可根据设置的大小预先设置字典的大小 ,并且可以在不对__hash __()进行任何新的调用的情况下填充字典:
>>> keys = {'red', 'green', 'blue', 'yellow', 'orange', 'pink', 'black'} >>> d = dict.fromkeys(keys) # dict is pre-sized to 32 empty slots
如果减less碰撞是您的目标,您可以对字典中的插入顺序进行实验,以最大限度地减less堆积。 (在Knuth的TAOCP中看看布伦特对algorithmD的变化,以了解这是如何完成的)。
通过为词典(比如这个词典)设置一个纯Python模型,可以计算替代插入顺序的加权平均探测次数。 例如,插入dict.fromkeys([11100, 22200, 44400, 33300])
平均每个查找1.75个探针。 这比dict.fromkeys([33300, 22200, 11100, 44400])
查找dict.fromkeys([33300, 22200, 11100, 44400])
2.25次平均探测次数。
另一个“诀窍”是通过在没有添加新密钥的情况下增加其大小来增加其大小,从而增加完全填充的字典中的空白:
d = dict.fromkeys(['red', 'green', 'blue', 'yellow', 'orange']) d.update(dict(d)) # This makes room for additional keys # and makes the set collision-free.
最后,您可以为您的密钥引入您自己的自定义__hash __(),以消除所有冲突(也许使用完美的哈希生成器,如gperf )。