The Python Oracle

Pythonic way to find maximum value and its index in a list?

--------------------------------------------------
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
and get $2,000 discount on your first invoice
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Forest of Spells Looping

--

Chapters
00:00 Pythonic Way To Find Maximum Value And Its Index In A List?
00:32 Accepted Answer Score 213
00:43 Answer 2 Score 384
01:31 Answer 3 Score 22
02:24 Answer 4 Score 21
02:44 Thank you

--

Full question
https://stackoverflow.com/questions/6193...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python

#avk47



ANSWER 1

Score 384


I think the accepted answer is great, but why don't you do it explicitly? I feel more people would understand your code, and that is in agreement with PEP 8:

max_value = max(my_list)
max_index = my_list.index(max_value)

This method is also about three times faster than the accepted answer:

import random
from datetime import datetime
import operator

def explicit(l):
    max_val = max(l)
    max_idx = l.index(max_val)
    return max_idx, max_val

def implicit(l):
    max_idx, max_val = max(enumerate(l), key=operator.itemgetter(1))
    return max_idx, max_val

if __name__ == "__main__":
    from timeit import Timer
    t = Timer("explicit(l)", "from __main__ import explicit, implicit; "
          "import random; import operator;"
          "l = [random.random() for _ in xrange(100)]")
    print "Explicit: %.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)

    t = Timer("implicit(l)", "from __main__ import explicit, implicit; "
          "import random; import operator;"
          "l = [random.random() for _ in xrange(100)]")
    print "Implicit: %.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)

Results as they run in my computer:

Explicit: 8.07 usec/pass
Implicit: 22.86 usec/pass

Other set:

Explicit: 6.80 usec/pass
Implicit: 19.01 usec/pass



ACCEPTED ANSWER

Score 213


There are many options, for example:

import operator
index, value = max(enumerate(my_list), key=operator.itemgetter(1))



ANSWER 3

Score 22


This answer is 33 times faster than @Escualo assuming that the list is very large, and assuming that it's already an np.array(). I had to turn down the number of test runs because the test is looking at 10000000 elements not just 100.

import random
from datetime import datetime
import operator
import numpy as np

def explicit(l):
    max_val = max(l)
    max_idx = l.index(max_val)
    return max_idx, max_val

def implicit(l):
    max_idx, max_val = max(enumerate(l), key=operator.itemgetter(1))
    return max_idx, max_val

def npmax(l):
    max_idx = np.argmax(l)
    max_val = l[max_idx]
    return (max_idx, max_val)

if __name__ == "__main__":
    from timeit import Timer

t = Timer("npmax(l)", "from __main__ import explicit, implicit, npmax; "
      "import random; import operator; import numpy as np;"
      "l = np.array([random.random() for _ in xrange(10000000)])")
print "Npmax: %.2f msec/pass" % (1000  * t.timeit(number=10)/10 )

t = Timer("explicit(l)", "from __main__ import explicit, implicit; "
      "import random; import operator;"
      "l = [random.random() for _ in xrange(10000000)]")
print "Explicit: %.2f msec/pass" % (1000  * t.timeit(number=10)/10 )

t = Timer("implicit(l)", "from __main__ import explicit, implicit; "
      "import random; import operator;"
      "l = [random.random() for _ in xrange(10000000)]")
print "Implicit: %.2f msec/pass" % (1000  * t.timeit(number=10)/10 )

Results on my computer:

Npmax: 8.78 msec/pass
Explicit: 290.01 msec/pass
Implicit: 790.27 msec/pass



ANSWER 4

Score 21


With Python's built-in library, it's pretty easy:

a = [2, 9, -10, 5, 18, 9] 
max(xrange(len(a)), key = lambda x: a[x])

This tells max to find the largest number in the list [0, 1, 2, ..., len(a)], using the custom function lambda x: a[x], which says that 0 is actually 2, 1 is actually 9, etc.