217

I have a list:

a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 55, 23, 31, 55, 21, 40, 18, 50,
             35, 41, 49, 37, 19, 40, 41, 31]

max element is 55 (two elements on position 9 and 12)

I need to find on which position(s) the maximum value is situated. Please, help.

Timur Shtatland
  • 12,024
  • 2
  • 30
  • 47
Bob
  • 10,427
  • 24
  • 63
  • 71

18 Answers18

378
a.index(max(a))

will tell you the index of the first instance of the largest valued element of list a.

nmichaels
  • 49,466
  • 12
  • 107
  • 135
  • 19
    This will only get you the first instance though and he asked for all the indexes where the largest value is found. You'd have to loop on that using slice to get the remaining list in each case and handling the exception when it's not found any longer. – jaydel Oct 21 '10 at 16:38
  • 11
    I did mention that it would only give the first instance. If you want all of them, SilentGhost's solution is much prettier and less error prone. – nmichaels Oct 21 '10 at 16:42
  • 9
    At least as I came to it, the question explicitly asks for a list in the case of multiple maxima... – emmagras Mar 25 '15 at 18:21
  • 2
    Technically, you could use this to get the first instance of the largest valued element and then set it to a ridiculously large negative number, and then find the next largest valued element, but that would be too complex. – Neil Oct 14 '17 at 17:15
  • @nmichaels Is there is any best way to get all positions of max value in a list than the accepted answer? – shaik moeed May 05 '19 at 07:17
  • 2
    It is explicitly saying "all". Please don't spam, the goal here is to help people as quickly as possible not to get badges and reputation (remove your answer if you're really trying to help). – Wildhammer Jan 20 '20 at 16:50
  • this is very good if you want an efficient way of finding max of a continuous list. – Javier Albarracin Jun 07 '20 at 11:11
260
>>> m = max(a)
>>> [i for i, j in enumerate(a) if j == m]
[9, 12]
SilentGhost
  • 307,395
  • 66
  • 306
  • 293
  • 5
    Nice short answer if you don't mind making multiple passes through the list -- which is likely. – martineau Oct 21 '10 at 19:06
  • Except the big 0 for this is 2n, the list is iterated through 2x, once to determine max, and another time to find the positions of the max. A for loop that tracks the current max and its position might be more efficient for really long lists. – radtek Jan 08 '15 at 18:42
  • 9
    @radtek big O is just n. leading coefficients are ignored in big O – michaelsnowden Oct 23 '15 at 08:06
  • 4
    Theoretically O(N) and O(2N) are the same but But practically, O(N) will definitely have a shorter running time, especially as N approaches infinity. – radtek Oct 24 '15 at 00:46
22

The chosen answer (and most others) require at least two passes through the list.
Here's a one pass solution which might be a better choice for longer lists.

Edited: To address the two deficiencies pointed out by @John Machin. For (2) I attempted to optimize the tests based on guesstimated probability of occurrence of each condition and inferences allowed from predecessors. It was a little tricky figuring out the proper initialization values for max_val and max_indices which worked for all possible cases, especially if the max happened to be the first value in the list — but I believe it now does.

def maxelements(seq):
    ''' Return list of position(s) of largest element '''
    max_indices = []
    if seq:
        max_val = seq[0]
        for i,val in ((i,val) for i,val in enumerate(seq) if val >= max_val):
            if val == max_val:
                max_indices.append(i)
            else:
                max_val = val
                max_indices = [i]

    return max_indices
martineau
  • 119,623
  • 25
  • 170
  • 301
  • 4
    (1) The empty list handling needs attention. Should return `[]` as advertised ("Return list"). Code should be simply `if not seq: return []`. (2) Testing scheme in loop is sub-optimal: on average in random lists, condition `val < maxval` will be the most common but the above code takes 2 tests instead of one. – John Machin Oct 21 '10 at 21:44
  • +1 to @John Machin's comment for catching the inconsistency with the docstring and not letting me get away with posting sub-optimal code. To be truthful, since an answer was already accepted, I lost a bit of motivation to continue working on my answer, since I assumed hardly anyone further would even look at it -- and it's so much longer than everyone else's. – martineau Oct 21 '10 at 22:55
  • 1
    @martineau: "accepted" answers are not necessarily "acceptable". I generally read all answers. Including your revision. Which does 3 tests now in the rare case of `==` instead of 2 -- your `elif` condition will always be true. – John Machin Oct 21 '10 at 23:21
  • @John Machin: I got really inspired and revised it even further. Now it's down minimumal additional tests, plus a few other tweaks. Thanks for your comments and constructive criticisms. I caught the always True `elif` myself, FWIW. ;-) – martineau Oct 21 '10 at 23:55
  • @John Machin: Hmmm, your timing results seem to contradict my own, so I will remove what I said in my answer about timing so I can look into what's going on further. Thanks for the heads-up. Actually I think a "real" timing test would need to use random list values. – martineau Oct 22 '10 at 02:05
  • @John Machin: To follow up, yep, I made a dumb mistake when performing my timing tests, so the results were totally bogus. Anyway, with regards to your more accurate results, I guess there's almost no beating the built-ins for pure speed short of writing an external C module. – martineau Oct 22 '10 at 14:29
  • @JohnMachin this might still be the best solution if the input is an iterator rather than a list. I just [asked about that](http://stackoverflow.com/questions/41155065/find-all-items-with-maximum-value-produced-by-an-iterator). – max Dec 15 '16 at 01:43
19

I came up with the following and it works as you can see with max, min and others functions over lists like these:

So, please consider the next example list find out the position of the maximum in the list a:

>>> a = [3,2,1, 4,5]

Using the generator enumerate and making a casting

>>> list(enumerate(a))
[(0, 3), (1, 2), (2, 1), (3, 4), (4, 5)]

At this point, we can extract the position of max with

>>> max(enumerate(a), key=(lambda x: x[1]))
(4, 5)

The above tells us, the maximum is in the position 4 and his value is 5.

As you see, in the key argument, you can find the maximum over any iterable object by defining a lambda appropriate.

I hope that it contributes.

PD: As @PaulOyster noted in a comment. With Python 3.x the min and max allow a new keyword default that avoid the raise exception ValueError when argument is empty list. max(enumerate(list), key=(lambda x:x[1]), default = -1)

Paul Oyster
  • 1,133
  • 1
  • 12
  • 21
Jonathan Prieto-Cubides
  • 2,577
  • 2
  • 18
  • 17
  • 4
    This is a better solution, since it involves a single pass. A few comments, though: 1. no need to list() the enumeration, 2. lambda better be parenthesized, 3. min() and max() now have a default parameter (which is returned on empty input), so can use it (default=-1, for example) to avoid a ValueError exception, and 4. please change to max(), as this was the original question. – Paul Oyster Mar 27 '15 at 15:40
  • about 3 item, yes, it just works with Python 3.x. I'll mention that. And fixed everything else. ;) – Jonathan Prieto-Cubides Mar 27 '15 at 15:49
  • 5
    This would only find the position of one of the maximum valued elements (the first) when it occurs more than once in the list—so doesn't answer the question asked. – martineau Oct 22 '18 at 10:43
  • This solution is slightly different from what OP asked but if we just want to find the max index in one pass this seems to be a better approach. I would suggest to have `default = (None, None)` as it fits the return type in case I am assigning to some variables like `max_index, max_value = max(enumerate(list), key=(lambda x:x[1]), default = (None, None))` – rainversion_3 Aug 29 '20 at 17:15
13

Also a solution, which gives only the first appearance, can be achieved by using numpy:

>>> import numpy as np
>>> a_np = np.array(a)
>>> np.argmax(a_np)
9
Green
  • 2,405
  • 3
  • 22
  • 46
11

I can't reproduce the @SilentGhost-beating performance quoted by @martineau. Here's my effort with comparisons:

=== maxelements.py ===

a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 55, 23, 31, 55, 21, 40, 18, 50,
             35, 41, 49, 37, 19, 40, 41, 31]
b = range(10000)
c = range(10000 - 1, -1, -1)
d = b + c

def maxelements_s(seq): # @SilentGhost
    ''' Return list of position(s) of largest element '''
    m = max(seq)
    return [i for i, j in enumerate(seq) if j == m]

def maxelements_m(seq): # @martineau
    ''' Return list of position(s) of largest element '''
    max_indices = []
    if len(seq):
        max_val = seq[0]
        for i, val in ((i, val) for i, val in enumerate(seq) if val >= max_val):
            if val == max_val:
                max_indices.append(i)
            else:
                max_val = val
                max_indices = [i]
    return max_indices

def maxelements_j(seq): # @John Machin
    ''' Return list of position(s) of largest element '''
    if not seq: return []
    max_val = seq[0] if seq[0] >= seq[-1] else seq[-1]
    max_indices = []
    for i, val in enumerate(seq):
        if val < max_val: continue
        if val == max_val:
            max_indices.append(i)
        else:
            max_val = val
            max_indices = [i]
    return max_indices

Results from a beat-up old laptop running Python 2.7 on Windows XP SP3:

>\python27\python -mtimeit -s"import maxelements as me" "me.maxelements_s(me.a)"
100000 loops, best of 3: 6.88 usec per loop

>\python27\python -mtimeit -s"import maxelements as me" "me.maxelements_m(me.a)"
100000 loops, best of 3: 11.1 usec per loop

>\python27\python -mtimeit -s"import maxelements as me" "me.maxelements_j(me.a)"
100000 loops, best of 3: 8.51 usec per loop

>\python27\python -mtimeit -s"import maxelements as me;a100=me.a*100" "me.maxelements_s(a100)"
1000 loops, best of 3: 535 usec per loop

>\python27\python -mtimeit -s"import maxelements as me;a100=me.a*100" "me.maxelements_m(a100)"
1000 loops, best of 3: 558 usec per loop

>\python27\python -mtimeit -s"import maxelements as me;a100=me.a*100" "me.maxelements_j(a100)"
1000 loops, best of 3: 489 usec per loop
John Machin
  • 81,303
  • 11
  • 141
  • 189
10

You can also use the numpy package:

import numpy as np
A = np.array(a)
maximum_indices = np.where(A==max(a))

This will return an numpy array of all the indices that contain the max value

if you want to turn this to a list:

maximum_indices_list = maximum_indices.tolist()
user3569257
  • 117
  • 1
  • 2
7
a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 
         55, 23, 31, 55, 21, 40, 18, 50,
         35, 41, 49, 37, 19, 40, 41, 31]

import pandas as pd

pd.Series(a).idxmax()

9

That is how I usually do it.

inanutshellus
  • 9,683
  • 9
  • 53
  • 71
Arijit Laha
  • 71
  • 1
  • 1
6
>>> max(enumerate([1,2,3,32,1,5,7,9]),key=lambda x: x[1])
>>> (3, 32)
Hari Roshan
  • 344
  • 4
  • 10
5

@shash answered this elsewhere

A Pythonic way to find the index of the maximum list element would be

position = max(enumerate(a), key=lambda x: x[1])[0]

Which does one pass. Yet, it is slower than the solution by @Silent_Ghost and, even more so, @nmichaels:

for i in s m j n; do echo $i;  python -mtimeit -s"import maxelements as me" "me.maxelements_${i}(me.a)"; done
s
100000 loops, best of 3: 3.13 usec per loop
m
100000 loops, best of 3: 4.99 usec per loop
j
100000 loops, best of 3: 3.71 usec per loop
n
1000000 loops, best of 3: 1.31 usec per loop
Community
  • 1
  • 1
serv-inc
  • 35,772
  • 9
  • 166
  • 188
3

Just one line:

idx = max(range(len(a)), key = lambda i: a[i])
divkakwani
  • 99
  • 1
  • 3
2

Similar idea with a list comprehension but without enumerate

m = max(a)
[i for i in range(len(a)) if a[i] == m]
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
  • I'm not the downvoter, but note that this doesn't look really nice and won't perform well: iterating through the indices instead of through the list is very awkward in Python, you try to avoid this. As well, it's certainly slower than the solution with enumerate because of the `a[i]` call. – yo' Aug 08 '14 at 14:07
2

Here is the max value and the indexes it appears at:

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 55, 23, 31, 55, 21, 40, 18, 50, 35, 41, 49, 37, 19, 40, 41, 31]
>>> for i, x in enumerate(a):
...     d[x].append(i)
... 
>>> k = max(d.keys())
>>> print k, d[k]
55 [9, 12]

Later: for the satisfaction of @SilentGhost

>>> from itertools import takewhile
>>> import heapq
>>> 
>>> def popper(heap):
...     while heap:
...         yield heapq.heappop(heap)
... 
>>> a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 55, 23, 31, 55, 21, 40, 18, 50, 35, 41, 49, 37, 19, 40, 41, 31]
>>> h = [(-x, i) for i, x in enumerate(a)]
>>> heapq.heapify(h)
>>> 
>>> largest = heapq.heappop(h)
>>> indexes = [largest[1]] + [x[1] for x in takewhile(lambda large: large[0] == largest[0], popper(h))]
>>> print -largest[0], indexes
55 [9, 12]
hughdbrown
  • 47,733
  • 20
  • 85
  • 108
2

If you want to get the indices of the largest n numbers in a list called data, you can use Pandas sort_values:

pd.Series(data).sort_values(ascending=False).index[0:n]
tuomastik
  • 4,559
  • 5
  • 36
  • 48
dannyg
  • 21
  • 1
1

Here's a simple single-pass solution.

import math
nums = [32, 37, 28, 30, 37, 25, 55, 27, 24, 35, 55, 23, 31]

max_val = -math.inf
res = []

for i, val in enumerate(nums):
    if(max_val < val):
        max_val = val
        res = [i]
    elif(max_val == val):
        res.append(i)
print(res)
sam
  • 95
  • 1
  • 1
  • 12
0

This code is not as sophisticated as the answers posted earlier but it will work:

m = max(a)
n = 0    # frequency of max (a)
for number in a :
    if number == m :
        n = n + 1
ilist = [None] * n  # a list containing index values of maximum number in list a.
ilistindex = 0
aindex = 0  # required index value.    
for number in a :
    if number == m :
        ilist[ilistindex] = aindex
        ilistindex = ilistindex + 1
    aindex = aindex + 1

print ilist

ilist in the above code would contain all the positions of the maximum number in the list.

0
import operator

def max_positions(iterable, key=None, reverse=False):
  if key is None:
    def key(x):
      return x
  if reverse:
    better = operator.lt
  else:
    better = operator.gt

  it = enumerate(iterable)
  for pos, item in it:
    break
  else:
    raise ValueError("max_positions: empty iterable")
    # note this is the same exception type raised by max([])
  cur_max = key(item)
  cur_pos = [pos]

  for pos, item in it:
    k = key(item)
    if better(k, cur_max):
      cur_max = k
      cur_pos = [pos]
    elif k == cur_max:
      cur_pos.append(pos)

  return cur_max, cur_pos

def min_positions(iterable, key=None, reverse=False):
  return max_positions(iterable, key, not reverse)

>>> L = range(10) * 2
>>> L
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> max_positions(L)
(9, [9, 19])
>>> min_positions(L)
(0, [0, 10])
>>> max_positions(L, key=lambda x: x // 2, reverse=True)
(0, [0, 1, 10, 11])
0

You can do it in various ways.

The old conventional way is,

maxIndexList = list() #this list will store indices of maximum values
maximumValue = max(a) #get maximum value of the list
length = len(a)       #calculate length of the array

for i in range(length): #loop through 0 to length-1 (because, 0 based indexing)
    if a[i]==maximumValue: #if any value of list a is equal to maximum value then store its index to maxIndexList
        maxIndexList.append(i)

print(maxIndexList) #finally print the list

Another way without calculating the length of the list and storing maximum value to any variable,

maxIndexList = list()
index = 0 #variable to store index
for i in a: #iterate through the list (actually iterating through the value of list, not index )
    if i==max(a): #max(a) returns a maximum value of list.
        maxIndexList.append(index) #store the index of maximum value
index = index+1 #increment the index

print(maxIndexList)

We can do it in Pythonic and smart way! Using list comprehension just in one line,

maxIndexList = [i for i,j in enumerate(a) if j==max(a)] #here,i=index and j = value of that index

All my codes are in Python 3.

Taohidul Islam
  • 5,246
  • 3
  • 26
  • 39