Получение индекса возвращаемого значения max или min с помощью max()/min() в списке

Я использую функции Python max и min в списках для минимаксного алгоритма, и мне нужен индекс значения, возвращаемого max() или min(). Другими словами, мне нужно знать, какой шаг произвел max (при первом повороте игрока) или min (второй игрок).

for i in range(9):
    newBoard = currentBoard.newBoardWithMove([i / 3, i % 3], player)

    if newBoard:
        temp = minMax(newBoard, depth + 1, not isMinLevel)  
        values.append(temp)

if isMinLevel:
    return min(values)
else:
    return max(values)

Мне нужно вернуть фактический индекс минимального или максимального значения, а не только значение.

Ответ 1

if isMinLevel:
    return values.index(min(values))
else:
    return values.index(max(values))

Ответ 2

Предположим, что у вас есть список values = [3,6,1,5] и нужен индекс наименьшего элемента, т.е. index_min = 2 в этом случае.

Избегайте решения с itemgetter(), представленного в других ответах, и используйте вместо этого

index_min = min(xrange(len(values)), key=values.__getitem__)

потому что для него не требуется import operator и не использовать enumerate, и он всегда быстрее (сравнительный тест ниже), чем решение с использованием itemgetter().

Если вы имеете дело с массивами numpy или можете позволить себе numpy в качестве зависимости, рассмотрите также использование

import numpy as np
index_min = np.argmin(values)

Это будет быстрее, чем первое решение, даже если вы примените его к чистым спискам Python, если:

  • он больше, чем несколько элементов (около 2 ** 4 элементов на моей машине).
  • вы можете предоставить копию памяти из чистого списка в массив numpy

как указывает этот критерий: введите описание изображения здесь

Я выполнил бенчмарк на своей машине с помощью python 2.7 для двух вышеперечисленных решений (синий: чистый python, первое решение) (красное, numpy-решение) и стандартное решение на основе itemgetter() (черное, ссылочное решение), Тот же тест с python 3.5 показал, что методы сравниваются точно так же, как и в случае python 2.7, представленном выше

Ответ 3

Вы можете найти индекс min и max одновременно, если вы перечисляете элементы в списке, но выполняете min/max в исходных значениях списка. Например:

import operator
min_index, min_value = min(enumerate(values), key=operator.itemgetter(1))
max_index, max_value = max(enumerate(values), key=operator.itemgetter(1))

Таким образом, список будет пройден только один раз для min (или max).

Ответ 4

Если вы хотите найти индекс max в списке чисел (что кажется вашим делом), то я предлагаю вам использовать numpy:

import numpy as np
ind = np.argmax(mylist)

Ответ 5

Возможно, более простым решением было бы превратить массив значений в массив значений, пары-индексы и взять max/min. Это даст наибольший/наименьший индекс с max/min (т.е. Пары сравниваются, сначала сравнивая первый элемент, а затем сравнивая второй элемент, если первые одинаковы). Обратите внимание: нет необходимости создавать массив, потому что min/max разрешают генераторы в качестве входных данных.

values = [3,4,5]
(m,i) = max((v,i) for i,v in enumerate(values))
print (m,i) #(5, 2)

Ответ 6

list=[1.1412, 4.3453, 5.8709, 0.1314]
list.index(min(list))

Дает вам первый указатель минимума.

Ответ 7

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

Оказывается, что numpy argmin,

numpy.argmin(x)

является самым быстрым методом для достаточно больших списков, даже с неявным преобразованием из входного list в numpy.array.

enter image description here


Код для создания участка:

import numpy
import operator
import perfplot


def min_enumerate(a):
    return min(enumerate(a), key=lambda x: x[1])[0]


def min_enumerate_itemgetter(a):
    min_index, min_value = min(enumerate(a), key=operator.itemgetter(1))
    return min_index


def getitem(a):
    return min(range(len(a)), key=a.__getitem__)


def np_argmin(a):
    return numpy.argmin(a)


perfplot.show(
    setup=lambda n: numpy.random.rand(n).tolist(),
    kernels=[
        min_enumerate,
        min_enumerate_itemgetter,
        getitem,
        np_argmin,
        ],
    n_range=[2**k for k in range(15)],
    logx=True,
    logy=True,
    )

Ответ 8

Используйте массив numpy и функцию argmax()

 a=np.array([1,2,3])
 b=np.argmax(a)
 print(b) #2

Ответ 9

После получения максимальных значений попробуйте следующее:

max_val = max(list)
index_max = list.index(max_val)

Гораздо проще, чем много вариантов.

Ответ 10

Я думаю, что лучше всего преобразовать список в numpy array и использовать эту функцию:

a = np.array(list)
idx = np.argmax(a)

Ответ 11

Я думаю, что ответ выше решает вашу проблему, но я думал, что поделился бы тем методом, который даст вам минимум и все индексы, в которых появляется минимум.

minval = min(mylist)
ind = [i for i, v in enumerate(mylist) if v == minval]

Это пропускает список дважды, но все еще довольно быстро. Это, однако, немного медленнее, чем поиск индекса первого столкновения минимума. Поэтому, если вам нужен только один из минимумов, используйте Matt Anderson, если они вам нужны, используйте это.

Ответ 12

Используйте функцию numpy module numpy.where

import numpy as n
x = n.array((3,3,4,7,4,56,65,1))

Для индекса минимального значения:

idx = n.where(x==x.min())[0]

Для индекса максимального значения:

idx = n.where(x==x.max())[0]

На самом деле эта функция намного мощнее. Вы можете создавать всевозможные булевы операции Для индекса от 3 до 60:

idx = n.where((x>3)&(x<60))[0]
idx
array([2, 3, 4, 5])
x[idx]
array([ 4,  7,  4, 56])

Ответ 13

Это просто возможно, используя встроенную функцию enumerate() и max() и необязательный аргумент key функции max() и простое выражение лямбда:

theList = [1, 5, 10]
maxIndex, maxValue = max(enumerate(theList), key=lambda v: v[1])
# => (2, 10)

В документах для max() говорится, что аргумент key ожидает функцию, как в list.sort(). Также см. Сортировка How To.

Он работает так же для min(). Btw возвращает первое значение max/min.

Ответ 14

Пока вы знаете, как использовать лямбда и аргумент "ключ", простое решение:

max_index = max( range( len(my_list) ), key = lambda index : my_list[ index ] )

Ответ 15

Скажем, у вас есть список, например:

a = [9,8,7]

Следующие два метода - довольно компактные способы получить кортеж с минимальным элементом и его индексом. Оба выполняют аналогичное время для обработки. Мне больше нравится метод zip, но это мой вкус.

почтовый метод

element, index = min(list(zip(a, range(len(a)))))

min(list(zip(a, range(len(a)))))
(7, 2)

timeit min(list(zip(a, range(len(a)))))
1.36 µs ± 107 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

метод перечисления

index, element = min(list(enumerate(a)), key=lambda x:x[1])

min(list(enumerate(a)), key=lambda x:x[1])
(2, 7)

timeit min(list(enumerate(a)), key=lambda x:x[1])
1.45 µs ± 78.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Ответ 16

Зачем сначала загружать индексы, а затем менять их? Функция Enumerate() - это особый случай использования функции zip(). Позвольте использовать его соответствующим образом:

my_indexed_list = zip(my_list, range(len(my_list)))

min_value, min_index = min(my_indexed_list)
max_value, max_index = max(my_indexed_list)

Ответ 17

Просто небольшое дополнение к тому, что уже было сказано. values.index(min(values)), кажется, возвращает наименьший индекс min. Следующий индекс получает наибольший индекс:

    values.reverse()
    (values.index(min(values)) + len(values) - 1) % len(values)
    values.reverse()

Последняя строка может быть опущена, если побочный эффект реверсирования на месте не имеет значения.

Для повторения всех вхождений

    indices = []
    i = -1
    for _ in range(values.count(min(values))):
      i = values[i + 1:].index(min(values)) + i + 1
      indices.append(i)

Для краткости. Вероятно, лучше кэшировать min(values), values.count(min) вне цикла.

Ответ 18

Простой способ поиска индексов с минимальным значением в списке, если вы не хотите импортировать дополнительные модули:

min_value = min(values)
indexes_with_min_value = [i for i in range(0,len(values)) if values[i] == min_value]

Затем выберите, например, первую:

choosen = indexes_with_min_value[0]

Ответ 19

Простое:

stuff = [2, 4, 8, 15, 11]

index = stuff.index(max(stuff))

Ответ 20

У вас недостаточно отзывов, чтобы прокомментировать существующий ответ.

Но для fooobar.com/questions/30795/... ответ

Это работает для целых чисел, но не работает для массива поплавков (по крайней мере, в python 3.6). Он будет вызывать TypeError: list indices must be integers or slices, not float

Ответ 21

https://docs.python.org/3/library/functions.html#max

Если несколько элементов являются максимальными, функция возвращает первый столбец. Это согласуется с другими инструментами сохранения стабильности сортировки, такими как sorted(iterable, key=keyfunc, reverse=True)[0]

Чтобы получить больше, чем просто первый метод сортировки.

import operator

x = [2, 5, 7, 4, 8, 2, 6, 1, 7, 1, 8, 3, 4, 9, 3, 6, 5, 0, 9, 0]

min = False
max = True

min_val_index = sorted( list(zip(x, range(len(x)))), key = operator.itemgetter(0), reverse = min )

max_val_index = sorted( list(zip(x, range(len(x)))), key = operator.itemgetter(0), reverse = max )


min_val_index[0]
>(0, 17)

max_val_index[0]
>(9, 13)

import ittertools

max_val = max_val_index[0][0]

maxes = [n for n in itertools.takewhile(lambda x: x[0] == max_val, max_val_index)]

Ответ 22

Как насчет этого:

a=[1,55,2,36,35,34,98,0]
max_index=dict(zip(a,range(len(a))))[max(a)]

Он создает словарь из элементов в a в качестве ключей и их индексов в качестве значений, поэтому dict(zip(a,range(len(a))))[max(a)] возвращает значение, соответствующее ключу max(a), который является индексом максимума в a. Я новичок в Python, поэтому я не знаю о вычислительной сложности этого решения.