当前位置: 首页 > 面试题库 >

改善Python中超大型字典的性能

上官飞
2023-03-14
问题内容

我发现如果在开始时初始化一个空字典,然后在for循环中向字典中添加元素(大约110,000个键,每个键的值是一个列表,并且在循环中也在增加),则速度会降低循环。

我怀疑问题在于,字典在初始化时不知道键的数量,并且执行的操作也不是很聪明,因此存储冲突可能会变得很频繁并且会减慢速度。

如果我知道键的数量以及这些键的确切含义,python中有什么方法可以使字典(或哈希表)更有效地工作?我隐约记得,如果您知道键,则可以巧妙地设计哈希函数(完美的哈希值?)并预先分配空间。


问题答案:

如果我知道键的数量以及这些键的确切含义,python中有什么方法可以使字典(或哈希表)更有效地工作?我隐约记得,如果您知道键,则可以巧妙地设计哈希函数(完美的哈希值?)并预先分配空间。

Python没有公开预定义大小的选项来加快字典的“成长阶段”,也没有提供对字典中“放置”的任何直接控制。

也就是说,如果始终事先知道键,则可以将它们存储在
集合中,
并使用
dict.fromkeys()

从该集合构建字典。该类方法已优化为根据设置的大小对字典进行预大小设置,并且可以填充字典而无需任何新的__hash
__()调用:

>>> keys = {'red', 'green', 'blue', 'yellow', 'orange', 'pink', 'black'}
>>> d = dict.fromkeys(keys)  # dict is pre-sized to 32 empty slots

如果要减少冲突是您的目标,则可以对字典中的插入顺序进行实验以最大程度地减少堆积。(看看Knuth的TAOCP中布伦特对算法D的变化,以了解如何完成此操作)。

通过为字典(例如this)使用纯Python模型,可以计算替代插入顺序的探针的加权平均数。例如,dict.fromkeys([11100, 22200,44400, 33300])每次查询平均插入1.75个探针。超过了每次查找的2.25次平均探查dict.fromkeys([33300, 22200,11100, 44400])

另一个“窍门”是通过愚弄它以增加其大小而不增加新的键s,从而增加完全填充的字典中的空缺:

 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 )。



 类似资料:
  • 问题内容: 有没有人对如何提高CSS3动画的流畅度有一些作弊技巧?我使用css过渡将整个页面向左滑动,比我想要的更加混乱。它是一个元素,但由于页面复杂,因此包含许多圆角,渐变,阴影等。 在Flash ActionScript中,有一个方便的属性,可以在动画开始之前将动画元素转换为位图。这是天赐之物,可显着加快某些类型的动画的速度。CSS有这样的东西吗?是否还有其他技巧可以在不简化页面设计的情况下提

  • 这几乎完全是视频练习,其中我演示了如何改进你至今为止编写的代码的性能,但首先你应该尝试它。你已经分析了 练习 18 的代码的速度有多慢,所以现在是时候实现你的一些想法。修复简单的性能问题时,我会给你一个简单的列表来寻找和修改: 循环内的循环的重复计算可以避免。冒泡排序是经典案例,这就是我教它的原因。,一旦你看到,冒泡排序与其他方法相比有多糟糕,你将开始认识到这是一个需要避免的常见模式。 重复计算一

  • 问题内容: 我有一本这样的字典: 我想获得该字典的5个最大值,并以此存储一个新的字典。要获得最大值,我做了: 也许这是一项容易的任务,但是我坚持了很长时间。请帮忙!!! 问题答案: 你近了 您可以使用 [docs] 对列表进行 排序 ,并采用前五个元素: __ 另请参阅:Python排序方法

  • 我需要生成一个非常大的文本文件。每一行都有一个简单的格式: 假设我要生成一个有1亿行的文件。我尝试了两种方法,令人惊讶的是,它们给出了非常不同的时间表现。 > 用于100m以上的循环。在每个循环中,我生成的短字符串,然后将其写入文件。这种方法需要很多时间。 请注意: 方法2有2个循环,而不是1个循环。 对于方法1和方法2,我都在循环中写入文件。因此这两个步骤必须相同。 因此方法1必须花费更少的时间

  • 问题内容: 我有这样的obj 它应该扩展到 我在下面编写了代码,按拆分,删除旧键,如果包含则追加新键,但是它说 对于obj.iteritems()中的k,v: RuntimeError:词典在迭代过程中更改了大小 问题答案: 就像消息说的那样:在循环遍历expand中的这些条目的过程中,您更改了expandField()内部obj中的条目数。 您可以尝试创建所需形式的新字典,或者以某种方式记录要进

  • 问题内容: 我有一张地图,其中填充了大量数据(大约有300,000条记录) 并如下迭代 } 如上所述,我担心由于在for循环内执行上述操作而导致的性能问题。 更新: 情况是。我正在迭代一个包含大量数据的地图, 在迭代它时,我正在获取用户ID,并且我必须对用户ID进行计算。例如,考虑userid+some constants并应该在数据库表中对其进行更新。 并且还应该与我地图中的列表值一起添加到电子