Newbie: finding the key/index of the min/max element

Alex Martelli aleax at aleax.it
Wed May 1 04:42:15 EDT 2002


James J. Besemer wrote:
        ...
> loop, but I think they're all less efficient and I'm not sure you could
> say any are more elegant.
> 
> E.g., you could say
> 
>     x = min( list )
>     minkey = list.index( x )
> 
> and do it in "two steps".  But this actually requires on average 1.5
> comparisons on the list, one to find the min and however many checks it
> takes to find that value again.
> 
> Then too, for small lists performance need not be a consideration. 

Right, but efficiency generally needs _measuring_.  Guesses are no good.

import time, sys, random

def imax_loop(seq):
    cmax = None
    i = 0
    for item in seq:
        if cmax is None or item>cmax:
            cmax = item
            imax = i
        i = i + 1
    return imax

def imax_noloop(seq):
    return seq.index(max(seq))

def imax_zip(seq):
    _idx = xrange(sys.maxint)
    return max(zip(seq,_idx))[1]

r = range(100000)
for i in range(4):
    random.shuffle(r)
    for f in imax_loop, imax_noloop, imax_zip:
        start = time.clock()
        x = f(r)
        stend = time.clock()
        print f.__name__,stend-start

[alex at lancelot GuiClient]$ python -O ima.py
imax_loop 0.12
imax_noloop 0.04
imax_zip 0.73
imax_loop 0.11
imax_noloop 0.05
imax_zip 0.69
imax_loop 0.1
imax_noloop 0.05
imax_zip 0.7
imax_loop 0.1
imax_noloop 0.05
imax_zip 0.69

So, performance doesn't really matter much -- but in as much as it does, 
the "noloop" approach wins hands down, taking 1/2 to 1/3 the time of
the "obvious" loop (forget the zip approach, clearly).

Since seq.index(max(seq)) is most concise, fastest, and quite clear,
I think it qualifies for "the one obvious way to do it" in this case.
Pity it doesn't work for mappings, only for sequences...


Alex




More information about the Python-list mailing list