【问题标题】:Creating (seeding) large dictionaries efficiently in Python在 Python 中高效地创建(播种)大型字典
【发布时间】:2014-02-07 08:54:39
【问题描述】:

我有一个长的(500K+ 行)两列电子表格,如下所示:

Name    Code
1234    A
1234    B
1456    C
4556    A
4556    B
4556    C
...

所以有一个元素(带有名称)可以有多个代码。但不是每个代码一行,我想列出每个元素出现的所有代码。我想要的是这样的字典:

{"1234":["A","B"],"1456":["C"],"4556":["A","B","C"] ...]}

我尝试过的是这个(我不包括文件读取语法)。


    codelist = {}
    for row in rows:
        name,code = well.split()
        if name in codelist.keys():
            codelist[name].append(code)
        else:
            codelist[name] = [code]

这会产生正确的输出,但进度会变得非常缓慢。所以我尝试用键启动我的字典:

allnames = [.... list of all the names ...]
codelist = dict.fromkeys(allnames)

for row in rows:

    name,code = well.split()
    if codelist[name]:
        codelist[name].append(code)
    else:
        codelist[name] = [code]

这要快得多,我的问题是为什么?程序不是每次都要搜索字典中的所有键吗?是否有另一种方法可以加快不包括遍历树的 dict 搜索?

有趣的是当我在启动字典后使用与以前相同的条件检查(如果在 codelist.keys():) 中使用相同的条件检查时遇到的错误。

Traceback (most recent call last):
  File .... 
    codelist[name].append(code)
AttributeError: 'NoneType' object has no attribute 'append'

现在,有一个键,但没有要附加的列表。所以我使用codelist[name],它也是<NoneType>,并且似乎可以工作。当mydict["primed key"]<NoneType> 时是什么意思?enter code here

【问题讨论】:

  • @AC,抱歉 - 从 IDLE 剪切/粘贴...应该是 {}。我已经编辑了帖子。
  • 不知道确切,但是您正在检查 codelist.keys(),这将创建一个列表或一个视图,而您可以执行 'name in codelist' 并直接进行查找

标签: python performance search dictionary


【解决方案1】:

前者速度较慢,因为.keys() 必须首先创建内存中所有键的列表,然后in 运算符对其执行搜索。因此,它是对文本文件中的每一行的O(N) 搜索,因此速度很慢。

另一方面,简单的key in dict 搜索需要O(1) 时间。

dict.fromkeys(allnames)

dict.fromkeys分配的默认值是None,所以不能在上面使用append

>>> d = dict.fromkeys('abc')
>>> d
{'a': None, 'c': None, 'b': None}

更好的解决方案是在此处使用collections.defaultdict,如果这不是一个选项,则使用普通的dict 并进行简单的if-else 检查或dict.setdefault


在 Python3 中,.keys() 返回一个视图对象,因此时间复杂度可能会有所不同。但是,它仍然会比正常的key in dict 搜索稍慢。

【讨论】:

    【解决方案2】:

    您可能想查看defaultdict 容器以避免检查

    from collections import defaultdict
    
    allnames [.... list of all the names ...]
    codelist = defaultdict(list)
    
    for row in rows:
    
        name,code = well.split()
        codelist[name].append(code)
    

    【讨论】:

      猜你喜欢
      • 2012-01-16
      • 2016-07-27
      • 2019-08-07
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多