Получение индекса возвращенного элемента max или min с использованием max () / min () в списке - PullRequest
356 голосов
/ 19 марта 2010

Я использую функции Python 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)

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

Ответы [ 21 ]

390 голосов
/ 06 августа 2012

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

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

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

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

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

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

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

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

как указывает этот тест: enter image description here

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

312 голосов
/ 19 марта 2010

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

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

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

300 голосов
/ 19 марта 2010
if isMinLevel:
    return values.index(min(values))
else:
    return values.index(max(values))
104 голосов
/ 23 ноября 2012

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

import numpy as np
ind = np.argmax(mylist)
34 голосов
/ 21 декабря 2012

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

values = [3,4,5]
(m,i) = max((v,i) for i,v in enumerate(values))
print (m,i) #(5, 2)
26 голосов
/ 08 сентября 2013
list=[1.1412, 4.3453, 5.8709, 0.1314]
list.index(min(list))

Даст вам первый индекс минимума.

12 голосов
/ 23 мая 2017

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

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

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 голосов
/ 29 января 2018

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

 a=np.array([1,2,3])
 b=np.argmax(a)
 print(b) #2
7 голосов
/ 11 января 2018

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

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

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

6 голосов
/ 16 апреля 2015

Использовать функцию numpy модуля 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])
...