使用未知密钥初始化大型字典?有比这更好的方法吗?

时间:2014-09-04 02:02:02

标签: python performance dictionary

所以我有一个大约75000个元组的列表,我想把它推入一个词典。似乎在大约20,000个条目之后,整个程序变慢,我认为这是因为dict在填充时动态调整大小。

用于dict的键值在元组中位于不同的位置,具体取决于数据,所以我不能只将元组列表中的键提取到列表x中并调用d.fromkeys(x)到pre - 初始化大字典。我已经尝试了一个解决方案,但是在通过ast.literal_eval评估dict之后,我得到的只是一个{'无':'无'}:/

我的溶解(不起作用)。

    d_frame = '{'+('\'None\': \'None\',' * 100000)+'}'
    d = ast.literal_eval(d_frame)

是否有类似这样的内置方法..

谢谢,

编辑:我意识到我的想法很愚蠢。显然你不能在词典中使用相同的键....:/

为了澄清,我有一个包含这样数据的元组列表:

 (assembly,strand,start_pos,end_pos,read_count)
 key_format : assembly_strand_val ( where val = start_pos or end_pos depending on other factors )

因为在我评估每个元组之前我不知道密钥,所以我不能用已知的密钥初始化dict,所以只是想知道我是否可以创建一个空的dict然后添加到它..它不会使感觉每个元组只是为了建立一个列表然后创建一个字典然后重复元组eval ...

编辑:我意识到瓶颈在哪里。每个元组,我都在检查相关的键是否已经在dict中退出,但我正在使用;

if key not in dict.keys():
    dict[key] = foo

我没有意识到每次都会建立一个密钥列表,并且可以用更经济的

替换
if key not in dict:
   dict[key] = foo

改变这种情况导致速度惊人地增加......

1 个答案:

答案 0 :(得分:7)

  

所以我有一个大约75000个元组的列表,我想把它推入一个字典。

只需在列表中拨打dict即可。像这样:

>>> list_o_tuples = [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
>>> d = dict(list_o_tuples)
>>> d
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}

  

用于dict的键值在元组中位于不同的位置,具体取决于数据

您向我们展示的代码根本没有证明这一点,但是如果您可以编写表达式或函数来拉出键,您可以在dict理解中使用它,或者在您可以传递的生成器表达式中使用它到dict函数。

例如,假设元组的第一个元素是实际键元素的索引。那你就写下来了:

d = {tup[tup[0]]: tup for tup in list_o_tuples}

  

似乎在大约20,000个条目之后,整个程序变慢,我认为这是因为dict在填充时动态调整大小。

这似乎不太可能。是的,dict已经调整了大小,但它已经成倍增长,并且在大小超过20000的情况下它仍然非常快。描述你的程序,看看它实际上在减慢速度。我的猜测要么是你正在做一些二次工作来创建或取出值,或者你正在产生大量的存储空间并导致交换,这两者都与将值插入到dict中无关。 / p>

无论如何,如果你真的想要“预先填写”字典,你可以随时这样做:

d = dict.from_keys(range(100000))
for i, tup in enumerate(list_o_tuples):
    del d[i]
    d[list_o_tuples[0]] = list_o_tuples[1]

然后dict永远不必调整大小。 (显然,如果你的密钥与0-99999的整数重叠,你会想要使用不同的填充键,但同样的想法也可以。)

但是我愿意打赌,这对你的表现没有任何影响。


  

我已尝试整理解决方案,但在ast.literal_eval评估dict后,我得到的只是一个{'None': 'None'}

那是因为你正在创建一个带有相同密钥的100K副本的字典。你不能在dict中有重复的键,所以当然你最终只有一个项目。

然而,这是一只红鲱鱼。创建一个字符串到eval几乎不是答案。你的大量代码实际上只是一个更慢,更低内存效率和更难阅读的版本:

d = {'None': 'None' for _ in range(100000)}

或者,如果您愿意:

d = dict([('None', 'None')] * 100000)