use*_*839 2 python performance dictionary
所以我有一个大约75000个元组的列表,我想要进入一个词典.似乎在大约20,000个条目之后,整个程序变慢并且我认为这是因为dict在被填充时被动态调整大小.
根据数据,用于dict的键值位于元组中的不同位置,因此我不能只将元组列表中的键提取到列表x中并调用d.fromkeys(x)来预先初始化大字典.我已经尝试了一个解决方案,但是在通过ast.literal_eval评估dict之后,我得到的只是一个{'None':'None'}:/
我的溶解(这不起作用).
d_frame = '{'+('\'None\': \'None\',' * 100000)+'}'
d = ast.literal_eval(d_frame)
Run Code Online (Sandbox Code Playgroud)
是否有这样的内置方法..
谢谢,
编辑:我意识到我的想法的愚蠢..显然你不能在字典中有相同的键....:/
为了澄清,我有一个包含这样数据的元组列表:
(assembly,strand,start_pos,end_pos,read_count)
key_format : assembly_strand_val ( where val = start_pos or end_pos depending on other factors )
Run Code Online (Sandbox Code Playgroud)
因为在我评估每个元组之前我不知道密钥,所以我不能用已知的密钥初始化dict,所以只是想知道我是否可以创建一个空的dict然后添加它..它没有意义去污染每个元组只是为了建立一个列表然后创建一个字典然后重复元组评估...
编辑:我意识到瓶颈在哪里..每个元组,我都在检查相关的键是否已经在dict中退出,但我正在使用;
if key not in dict.keys():
dict[key] = foo
Run Code Online (Sandbox Code Playgroud)
我没有意识到每次都会建立一个密钥列表,并且可以用更加经济的方式替换
if key not in dict:
dict[key] = foo
Run Code Online (Sandbox Code Playgroud)
改变这种情况导致速度惊人地增加......
所以我有一个大约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'}
Run Code Online (Sandbox Code Playgroud)
根据数据,用于dict的键值位于元组中的不同位置
您向我们展示的代码根本没有证明这一点,但是如果您可以编写表达式或函数来拉出键,您可以在dict理解中使用它,或者在生成器表达式中使用它可以传递给dict
函数.
例如,假设元组的第一个元素是实际键元素的索引.然后你写这个:
d = {tup[tup[0]]: tup for tup in list_o_tuples}
Run Code Online (Sandbox Code Playgroud)
似乎在大约20,000个条目之后,整个程序变慢并且我认为这是因为dict在被填充时被动态调整大小.
这似乎不太可能.是的,字典调整大小,但它这样做的指数增长,而它仍然是极快的尺寸远远超出20000简介你的程序,看看它的实际放缓.我的猜测要么是你正在做一些二次工作来创建或取出值,或者你正在生成大量存储并导致交换,这两者都与将值插入dict有关.
无论如何,如果你真的想"预先填写"字典,你可以随时这样做:
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]
Run Code Online (Sandbox Code Playgroud)
然后dict永远不必调整大小.(显然,如果你的密钥与0-99999的整数重叠,你会想要使用不同的填充键,但同样的想法也可以.)
但我愿意打赌,这对你的表现完全没有影响.
我已经尝试过组合一个解决方案,但是在评估dict之后
ast.literal_eval
,我得到的只是一个{'None': 'None'}
那是因为你正在创建一个带有相同密钥的100K副本的字典.你不能在dict中有重复的键,所以当然你最终只有一个项目.
然而,这是一个红鲱鱼.创建一个字符串到eval几乎不是答案.你的大量代码实际上只是一个更慢,更低内存效率和更难阅读的版本:
d = {'None': 'None' for _ in range(100000)}
Run Code Online (Sandbox Code Playgroud)
或者,如果您愿意:
d = dict([('None', 'None')] * 100000)
Run Code Online (Sandbox Code Playgroud)