确定列表中最大值的索引 - 优化

时间:2013-02-01 12:04:24

标签: python optimization

我已经写了几行代码来解决这个问题,但是分析师说,这是非常耗时的。 (使用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?

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:3)

如果您多次这样做,并且如果您同时拥有所有列表,则可以numpy.argmax {{1}}获取所有列表的索引。

答案 2 :(得分:2)

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

这就是说,我可以想到一个小优化 - 对set使用list而不是max_where理解。这将使您的三次会员资格测试更快。

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

也就是说,只有三项/支票,这套装置的构造可能比节省时间更长。

通常,如果列出三个项目,此操作将花费可忽略的时间。在我的系统上,执行此操作需要半微秒

简而言之:不要打扰。除非这是您的程序中经过验证的瓶颈,需要加速,否则您当前的代码就可以了。

答案 3 :(得分: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]轻松访问该项目(以及循环给出的索引)。

奇怪的是,托比亚斯的实施似乎更快(我不这么认为):

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)的长列表。

答案 4 :(得分: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]

这与上面的其他解决方案非常相似。我知道有些时间过去了,但事情并非如此。 :)

干杯!