警告,这有点递归;)
我回答了这个问题:Python:How can i get all the elements in a list before the longest element?
在我提交之后,另一个应该更快的答案(作者认为,我也是如此)。我试图计算不同的解决方案,但应该更慢的解决方案实际上更快。这让我觉得我的代码有问题。或者是吗?
import string
import random
import time
def solution1(lst):
return lst[:lst.index(max(lst, key=len))]
def solution2(lst):
idx, maxLenStr = max(enumerate(lst), key=lambda x:len(x[1]))
return lst[:idx]
# Create a 100000 elements long list that contains
# random data and random element length
lst = []
for i in range(100000):
s = "".join([random.choice(string.letters+string.digits) for x in range(1, random.randint(1,50))])
lst.append(s)
# Time the first solution
start = time.time()
solution1(lst)
print 'Time for solution1', (time.time() - start)
# Time the second solution
start = time.time()
solution2(lst)
print 'Time for solution2', (time.time() - start)
在有人提到我之前为什么这是一个新问题。问题更多是关于我学习如何衡量执行时间......
答案 0 :(得分:3)
似乎第一个版本的呼叫次数少于第二个版本。
btw,这可能是另一个例子,说明惯用的,简单的代码通常也是Python中更快的代码
>>> dis.dis(solution1)
2 0 LOAD_FAST 0 (lst)
3 LOAD_FAST 0 (lst)
6 LOAD_ATTR 0 (index)
9 LOAD_GLOBAL 1 (max)
12 LOAD_FAST 0 (lst)
15 LOAD_CONST 1 ('key')
18 LOAD_GLOBAL 2 (len)
21 CALL_FUNCTION 257
24 CALL_FUNCTION 1
27 SLICE+2
28 RETURN_VALUE
>>> dis.dis(solution2)
2 0 LOAD_GLOBAL 0 (max)
3 LOAD_GLOBAL 1 (enumerate)
6 LOAD_FAST 0 (lst)
9 CALL_FUNCTION 1
12 LOAD_CONST 1 ('key')
15 LOAD_CONST 2 (<code object <lambda> at 000000000422BEB8, file "<input>", line 2>)
18 MAKE_FUNCTION 0
21 CALL_FUNCTION 257
24 UNPACK_SEQUENCE 2
27 STORE_FAST 1 (idx)
30 STORE_FAST 2 (maxLenStr)
3 33 LOAD_FAST 0 (lst)
36 LOAD_FAST 1 (idx)
39 SLICE+2
40 RETURN_VALUE
答案 1 :(得分:3)
在第二种解决方案中,lambda的成本越来越高。
我分析了代码和配置文件数据,看起来,第一个解决方案更快
由于wiki会说函数调用成本很高,而在第二种解决方案中,lambda和len函数调用会使它运行得更慢
请注意,我已将列表缩减为1000个元素的长度
>>> cProfile.run('solution1(lst)')
5 function calls in 0.000 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 <pyshell#305>:1(solution1)
1 0.000 0.000 0.000 0.000 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {max}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {method 'index' of 'list' objects}
>>> cProfile.run('solution2(lst)')
2004 function calls in 0.012 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.012 0.012 <pyshell#306>:1(solution2)
1000 0.006 0.000 0.009 0.000 <pyshell#306>:2(<lambda>)
1 0.000 0.000 0.012 0.012 <string>:1(<module>)
1000 0.003 0.000 0.003 0.000 {len}
1 0.003 0.003 0.012 0.012 {max}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
答案 2 :(得分:2)
时机看起来不错。
solution1
可以更快,因为它不使用lambdas,因此它不需要在循环中调用Python代码。它会对列表进行两次迭代,但这不是什么大问题。