Как найти все позиции максимального значения в списке? - PullRequest
122 голосов
/ 21 октября 2010

У меня есть список:

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]

Максимальный элемент 55 (два элемента в позициях 9 и 12)

Мне нужно найти, в какой позиции (ях) максимальное значениерасположенный.Пожалуйста, помогите.

Ответы [ 16 ]

262 голосов
/ 21 октября 2010
a.index(max(a))

сообщит вам индекс первого экземпляра элемента с наибольшим значением в списке a.

179 голосов
/ 21 октября 2010
>>> m = max(a)
>>> [i for i, j in enumerate(a) if j == m]
[9, 12]
18 голосов
/ 21 октября 2010

Выбранный ответ (и большинство других) требует как минимум двух проходов по списку.
Вот одноходовое решение, которое может быть лучшим выбором для длинных списков.

Отредактировано: Для устранения двух недостатков, указанных @John Machin. Для (2) я попытался оптимизировать тесты, основанные на предположительной вероятности возникновения каждого условия и выводов, допускаемых предшественниками. Было немного сложно выяснить правильные значения инициализации для max_val и max_indices, которые работали для всех возможных случаев, особенно если max оказалось первым значением в списке - но я верю, что теперь это так.

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
8 голосов
/ 22 октября 2010

Я не могу воспроизвести выступление @ SilentGhost, которое цитирует @martineau.Вот мои усилия по сравнению:

=== 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

Результаты изношенного старого ноутбука с Python 2.7 на 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
7 голосов
/ 06 марта 2015

Я придумал следующее, и оно работает, как вы можете видеть с max, min и другими функциями над списками, подобными этим:

Итак, пожалуйста, рассмотрите следующий пример списка, чтобы узнать позицию максимум в списке a:

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

Использование генератора enumerate и создание кастинга

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

В этот момент мы можем извлечь позицию max с помощью

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

. Выше сказано, что максимум находится в позиции 4, а его значение равно 5.

Как видите, в аргументе key вы можете найти максимум для любого итерируемого объекта, определив соответствующую лямбду.

Я надеюсь, что это способствует.

PD: Как отметил @PaulOyster в комментарии.С Python 3.x min и max позволяют новое ключевое слово default, которое исключает исключение повышения ValueError, когда аргумент является пустым списком.max(enumerate(list), key=(lambda x:x[1]), default = -1)

6 голосов
/ 24 мая 2016
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

Так я обычно делаю.

5 голосов
/ 15 октября 2014

Вы также можете использовать пакет numpy:

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

Это вернет массив numey всех индексов, которые содержат максимальное значение

, если вы хотите превратить его в список:

maximum_indices_list = maximum_indices.tolist()
4 голосов
/ 12 ноября 2015
>>> max(enumerate([1,2,3,32,1,5,7,9]),key=lambda x: x[1])
>>> (3, 32)
3 голосов
/ 05 ноября 2015

@ shash ответил на это в другом месте

Pythonic способ найти индекс элемента максимального списка будет

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

Что делает один проход . Тем не менее, это медленнее, чем решение @Silent_Ghost и, тем более, @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
2 голосов
/ 26 декабря 2013

Аналогичная идея с пониманием списка, но без перечисления

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