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