How to find all positions of the maximum value in a list?

PythonListIndexingMax

Python Problem Overview


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.

Python Solutions


Solution 1 - Python

a.index(max(a))

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

Solution 2 - Python

>>> m = max(a)
>>> [i for i, j in enumerate(a) if j == m]
[9, 12]

Solution 3 - Python

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

Solution 4 - Python

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)

Solution 5 - Python

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

Solution 6 - Python

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

Solution 7 - Python

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()

Solution 8 - Python

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.

Solution 9 - Python

>>> max(enumerate([1,2,3,32,1,5,7,9]),key=lambda x: x[1])
>>> (3, 32)

Solution 10 - Python

@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: x1)[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

Solution 11 - Python

Just one line:

idx = max(range(len(a)), key = lambda i: a[i])

Solution 12 - Python

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]

Solution 13 - Python

Similar idea with a list comprehension but without enumerate

m = max(a)
[i for i in range(len(a)) if a[i] == m]

Solution 14 - Python

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]

Solution 15 - Python

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.

Solution 16 - Python

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)

Solution 17 - Python

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])

Solution 18 - Python

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBobView Question on Stackoverflow
Solution 1 - PythonnmichaelsView Answer on Stackoverflow
Solution 2 - PythonSilentGhostView Answer on Stackoverflow
Solution 3 - PythonmartineauView Answer on Stackoverflow
Solution 4 - PythonJonathan Prieto-CubidesView Answer on Stackoverflow
Solution 5 - PythonGreenView Answer on Stackoverflow
Solution 6 - PythonJohn MachinView Answer on Stackoverflow
Solution 7 - Pythonuser3569257View Answer on Stackoverflow
Solution 8 - PythonArijit LahaView Answer on Stackoverflow
Solution 9 - PythonHari RoshanView Answer on Stackoverflow
Solution 10 - Pythonserv-incView Answer on Stackoverflow
Solution 11 - PythondivkakwaniView Answer on Stackoverflow
Solution 12 - PythonhughdbrownView Answer on Stackoverflow
Solution 13 - PythonSalvador DaliView Answer on Stackoverflow
Solution 14 - PythondannygView Answer on Stackoverflow
Solution 15 - PythonTaohidul IslamView Answer on Stackoverflow
Solution 16 - PythonsamView Answer on Stackoverflow
Solution 17 - PythonRoger PateView Answer on Stackoverflow
Solution 18 - PythonSukrit GuptaView Answer on Stackoverflow