Ответ 1
if isMinLevel: return values.index(min(values)) else: return values.index(max(values))
Я использую функции 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)
Мне нужно вернуть фактический индекс минимального или максимального значения, а не только значение.
if isMinLevel: return values.index(min(values)) else: return values.index(max(values))
Предположим, что у вас есть список 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, если:
numpy
Я выполнил бенчмарк на своей машине с помощью python 2.7 для двух вышеперечисленных решений (синий: чистый python, первое решение) (красное, numpy-решение) и стандартное решение на основе itemgetter()
(черное, ссылочное решение),
Тот же тест с python 3.5 показал, что методы сравниваются точно так же, как и в случае python 2.7, представленном выше
Вы можете найти индекс 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).
Если вы хотите найти индекс max в списке чисел (что кажется вашим делом), то я предлагаю вам использовать numpy:
import numpy as np
ind = np.argmax(mylist)
Возможно, более простым решением было бы превратить массив значений в массив значений, пары-индексы и взять 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)
list=[1.1412, 4.3453, 5.8709, 0.1314]
list.index(min(list))
Дает вам первый указатель минимума.
Я также интересовался этим и сравнивал некоторые из предлагаемых решений, используя perfplot (мой любимый проект).
Оказывается, что numpy argmin,
numpy.argmin(x)
является самым быстрым методом для достаточно больших списков, даже с неявным преобразованием из входного list
в numpy.array
.
Код для создания участка:
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,
)
Используйте массив numpy и функцию argmax()
a=np.array([1,2,3])
b=np.argmax(a)
print(b) #2
После получения максимальных значений попробуйте следующее:
max_val = max(list)
index_max = list.index(max_val)
Гораздо проще, чем много вариантов.
Я думаю, что лучше всего преобразовать список в numpy array
и использовать эту функцию:
a = np.array(list)
idx = np.argmax(a)
Я думаю, что ответ выше решает вашу проблему, но я думал, что поделился бы тем методом, который даст вам минимум и все индексы, в которых появляется минимум.
minval = min(mylist)
ind = [i for i, v in enumerate(mylist) if v == minval]
Это пропускает список дважды, но все еще довольно быстро. Это, однако, немного медленнее, чем поиск индекса первого столкновения минимума. Поэтому, если вам нужен только один из минимумов, используйте Matt Anderson, если они вам нужны, используйте это.
Используйте функцию 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])
Это просто возможно, используя встроенную функцию 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.
Пока вы знаете, как использовать лямбда и аргумент "ключ", простое решение:
max_index = max( range( len(my_list) ), key = lambda index : my_list[ index ] )
Скажем, у вас есть список, например:
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)
Зачем сначала загружать индексы, а затем менять их? Функция 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)
Просто небольшое дополнение к тому, что уже было сказано.
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)
вне цикла.
Простой способ поиска индексов с минимальным значением в списке, если вы не хотите импортировать дополнительные модули:
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]
Простое:
stuff = [2, 4, 8, 15, 11]
index = stuff.index(max(stuff))
У вас недостаточно отзывов, чтобы прокомментировать существующий ответ.
Но для fooobar.com/questions/30795/... ответ
Это работает для целых чисел, но не работает для массива поплавков (по крайней мере, в python 3.6). Он будет вызывать TypeError: list indices must be integers or slices, not float
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)]
Как насчет этого:
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, поэтому я не знаю о вычислительной сложности этого решения.