【问题标题】:Python Function Takes too Long as Dictionary Gets too Big由于字典变得太大,Python 函数花费的时间太长
【发布时间】:2013-08-23 16:50:47
【问题描述】:
def assign_ID(dic,id):
  for key, value in enumerate(dic):
    for elem in range(value):
      if id in dic[value]:
        return value 

我上面的函数做了我想做的事——但问题是随着字典 dic 在我的程序的主要部分变得越来越大,我的“assign_ID”函数花费的时间太长。最初这个函数需要大约 1/100 秒的时间来运行,但是在几千行输入之后,它开始需要半秒,然后是一整秒,然后更长。问题是我的输入文件太大了,最终这个函数使整个程序至少需要两天时间才能运行。

有没有办法重写上面的函数,让它运行得更快?我希望能够定期运行这个程序,所以我真的希望它比它运行得更快。

非常感谢您的任何帮助!

【问题讨论】:

  • 我不认为enumerate(dic) 做你认为它做的事。你能描述一下你的数据结构和你想要完成的任务吗?
  • 当然,所以“dic”是一个默认字典(docs.python.org/release/2.5.2/lib/defaultdict-examples.html)。我的目标是查看之前是否已将相关 id 分配给一个键。我们一直遇到各种导致不同 id 的问题,所以我想彻底检查整个字典,看看值是否出现在其他地方。你会这样想吗?
  • defaultdict 的值是多少?如果它们是列表,并且列表变得很大,那么每个 in 运算符将花费大量时间。您应该考虑改用sets。
  • 呃...你有一个 O(n) 步骤与 for elem in range(value) 几乎什么都不做。
  • 如果您希望该值在整个数据集中只出现一次,那么列表字典是错误的数据结构。

标签: python performance dictionary


【解决方案1】:

好吧,马上,摆脱enumerate。此外,您的第二个 for 循环什么也不做。也摆脱它:

def assign_ID(dic, id):
    for key in dic:
        if id in dic[key]:
            return key

上面的函数应该做你旧函数所做的一切,只是它会快得多。

【讨论】:

  • @delnan - 好电话。我只是复制/粘贴了他的代码,所以我并没有真正注意到这一点。
  • 哦,现在我注意到另一个简化,密钥从未使用过,所以我们可以使用dic.values()。 (编辑:废话,见下文。)
  • @delnan:嗯,密钥返回了。虽然目前还不清楚是否需要这样做。
  • 由于 in-statement 中的隐含循环,这将具有二次性能。
【解决方案2】:

您可以使用iteritems 更有效地迭代字典项(在 Python 2.x 中):

for k,v in dic.iteritems():
    if id in v:
        return k

@Bakuriu 在 Python 3.x 中观察到:

for k,v in dic.items():
    if id in v:
        return k

因为在 Python 3.x 中 items() 将提供一个迭代器,类似于 Python 2.x 中的 iteritems()

【讨论】:

  • 请注意,iteritems() 在 python3 中已被删除。改用items()(这也适用于python2,尽管语义略有不同)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
相关资源
最近更新 更多