1

我写了几行代码来解决这个问题,但是分析器说,这非常耗时。(使用 kernprof 逐行分析器)这是代码:

comp = [1, 2, 3] #comp is list with always 3 elements, values 1, 2, 3 are just for illustration
m = max(comp)
max_where = [i for i, j in enumerate(comp) if j == m]
if 0 in max_where: 
    some action1
if 1 in max_where: 
    some action2
if 2 in max_where: 
    some action3

Profiler 表示大部分时间都花在 max_where 计算中。我也曾尝试将这个计算拆分成 if-tree 以避免一些不必要的操作,但结果并不令人满意。

请问,我做错了还是只是python?

4

5 回答 5

3

如果它总是三个元素,为什么不简单地做:

comp = [1, 2, 3] 
m = max(comp)

if comp[0] == m: 
    some action
if comp[1] == m: 
    some action
if comp[2] == m: 
    some action
于 2013-02-01T12:17:07.183 回答
3

如果您多次这样做,并且同时拥有所有可用列表,那么您可以利用numpy.argmax获取所有列表的索引。

于 2013-02-01T12:20:45.650 回答
2

您说这是一个耗时的操作,但我真诚地怀疑这是否会影响您的程序。您是否真的发现由于代码执行缓慢而导致了一些问题?如果没有,优化就没有意义了。

这就是说,我能想到一个小的优化——即使用 aset而不是listmax_where. 这将使您的三个成员资格测试更快。

max_where = {i for i, j in enumerate(comp) if j == m}

也就是说,只有三个项目/检查,集合的构建可能需要比它节省更多的时间。

通常,对于包含三个项目的列表,此操作将花费可忽略不计的时间。在我的系统上,执行此操作需要半微秒。

简而言之:不要打扰。除非这是您的程序中需要加速的已证明瓶颈,否则您当前的代码很好。

于 2013-02-01T12:15:03.233 回答
1

for使用循环扩展 Tobias 的答案:

comp = [1, 2, 3] 
m = max(comp)

for index in range(len(comp)):
    if comp[index] == m:
        # some action

由于索引从 0 开始,因此您不需要执行len(comp) + 1. 我更喜欢在循环中使用索引for而不是实际元素,因为它可以大大加快速度。有时在一个过程中,您可能需要特定元素的索引。然后,使用l.index(obj)会浪费时间(即使只是微不足道的数量——对于更长的过程,这会变得乏味)。

这也假设每个过程(对于comp[index])都非常相似:相同的过程但具有不同的变量。如果您对每个索引都有显着不同的过程,这将不起作用。

但是,通过使用for index in range(len(l)):,您已经有了索引,并且可以轻松地访问该项目l[index](连同由循环给出的索引)。

奇怪的是,Tobias 的实现似乎更快(我不这么认为):

comp = [1, 2, 3]
m = max(comp)
from timeit import timeit
def test1():
    if comp[0] == m: return m
    if comp[1] == m: return m
    if comp[2] == m: return m

def test2():
    for index in range(len(comp)):
        if comp[index] == m: return m

print 'test1:', timeit(test1, number = 1000)
print 'test2:', timeit(test2, number = 1000)

回报:

test1: 0.00121262329299
test2: 0.00469034990534

对于更长的列表,我的实现可能会更快(但不确定)。但是,为此编写代码很乏味(对于使用重复的长列表if comp[n] == m)。

于 2013-02-01T13:25:21.167 回答
1

这个怎么样:

sample = [3,1,2]    
dic = {0:func_a,1:func_b,2:func_c}
x = max(sample) 
y = sample.index(x)
dic[y]

如前所述并且正确地被否决,这不适用于多个函数调用。但是,这样做:

sample = [3,1,3]    
dic = {0:"func_a",1:"func_b",2:"func_c"}
max_val = max(sample) 
max_indices = [index for index, elem in enumerate(sample) if elem==max_val]
for key in max_indices:
    dic[key]

这与上述其他解决方案非常相似。我知道一段时间过去了,但它是不正确的。:)

干杯!

于 2013-02-01T16:01:06.757 回答