我正在解决这个python挑战http://coj.uci.cu/24h/problem.xhtml?abb=2634,这是我的答案
c = int(input())
l = []
for j in range(c) :
i = raw_input().split()[1].split('/')
l.append(int(i[1]))
for e in range(1,13) :
print e , l.count(e)
但它不是最快的python解决方案,所以我试图找到如何提高速度,我发现xrange比范围更快。但是,当我尝试以下代码时,它实际上更慢
c = int(input())
l = []
for j in xrange(c):
i = raw_input().split()[1].split('/')[1]
l.append(i)
for e in xrange(1,13) :
print e , l.count(`e`)
所以我有两个问题:
当我在寻找此信息时,我发现了这样的网站https://wiki.python.org/moin/PythonSpeed/PerformanceTips 但是它没有指定,例如,如果在单行或多行中多次拆分字符串更快/更慢,例如使用上面提到的部分脚本:
i = raw_input().split()[1].split('/')[1]
VS
i = raw_input().split()
i = i[1].split('/')
i = i[1]
编辑:我已经尝试了所有建议,但我的第一个答案仍然是最快的,我不知道为什么。我的冷杉答案是151毫秒,@ Bakuriu的回答是197毫秒,我的答案是使用collections.Counter是188毫秒。
编辑2:请忽略我上次编辑,我发现上面提到的检查代码性能的方法不起作用,如果你上传相同代码的次数超过每次性能不同有时候它更慢,有时更快
答案 0 :(得分:9)
假设您正在使用CPython,黄金法则是将尽可能多的工作推入内置函数,因为它们是用C语言编写的,因此避免了解释器开销。
这意味着你应该:
list
和dict
。标准库包含其他数据类型,并且有许多库。考虑哪个应该是解决问题的有效操作并选择正确的数据结构dis
模块反汇编字节码。这为您提供了一种简单的方法来查看解释器的真正功能。如果你真的想知道解释器是如何工作的,你应该尝试阅读包含解释器主循环的PyEval_EvalFrameEx
的源代码(注意: hic sunt leones !)。 关于CPython,你应该阅读Guido Van Rossum的An optimization anecdote。它提供了许多有关各种解决方案如何改变性能的见解。另一个例子可能是this回答(免责声明:这是我的),对于那些不习惯CPython工作的人来说,最快的解决方案可能非常直观。
另一个好处是研究所有最常用的内置和stdlib数据类型,因为每个数据类型都有正负比例。在这种特定情况下,调用list.count()
是一项繁重的操作,因为它必须在每次执行时扫描整个列表。这可能是您的解决方案消耗了大量时间。
最小化解释器开销的一种方法是使用collections.Counter
,这也避免了多次扫描数据:
from collections import Counter
counts = Counter(raw_input().split('/')[-2] for _ in range(int(raw_input())))
for i in range(1, 13):
print(i, counts[str(i)])
请注意,不需要将月份转换为整数,因此您可以避免这些函数调用(假设月份总是以相同的方式编写。没有07
和7
)。
此外,我不明白为什么要分割空格,然后在/
上,只需按/
拆分并从列表中取一个到最后一个元素。< / p>
另一个(重要的)优化可能是读取所有stdin
以避免多个IO调用,但是这可能不适用于这种情况,因为他们告诉您有多少员工可能意味着他们是不发送EOF。
请注意,不同版本的python具有完全不同的优化代码的方式。例如,当您在JIT能够分析和优化的循环中执行简单操作时,PyPy的JIT效果最佳。所以它与你在CPython中所做的相反。