web-dev-qa-db-ja.com

リストのmax()/ min()を使用して返された最大または最小項目のインデックスを取得する

私はミニマックスアルゴリズムのためにリスト上でPythonのmaxmin関数を使っています、そして私はmax()min()によって返される値のインデックスが必要です。言い換えれば、私はどの動きが最大値(最初のプレイヤーのターンに)または最小値(2番目のプレイヤー)を生み出したかを知る必要があります。

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)

値だけでなく、最小値または最大値の実際のインデックスを返すことができる必要があります。

346
Kevin Griffin
 if isMinLevel:
戻り値.index(min(values))
 else:
戻り値.index(max(values))
289
too much php

values = [3,6,1,5]というリストがあり、最小の要素のインデックス、この場合はindex_min = 2が必要だとします。

他の答えで示されているitemgetter()による解決を避け、代わりに使ってください

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

なぜなら、それはimport operatorenumerateを使う必要もなく、itemgetter()を使うソリューションよりも常に速いからです(下記のベンチマーク)。

あなたがテンキーな配列を扱っているか、依存関係としてnumpyを買う余裕があるならば、また使用を検討してください。

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

次のような場合に純粋なPythonリストに適用しても、これは最初の解決策よりも速くなります。

  • それはいくつかの要素よりも大きい(私のマシンでは約2 ** 4要素)
  • 純粋なリストからnumpy配列へのメモリコピーが可能です。

このベンチマークが指摘するように: enter image description here

上記の2つの解決策(青:純粋なpython、最初の解決策)(赤、派手な解決策)とitemgetter()に基づく標準解決策(黒、参照解決策)について、私は自分のマシンでpython 2.7を使ってベンチマークを実行しました。 python 3.5と同じベンチマークでは、これらのメソッドは上記のpython 2.7の場合とまったく同じであることがわかりました。

373
gg349

リスト内の項目を列挙しても、リストの元の値に対して最小/最大を実行すると、最小/最大インデックスと値を同時に見つけることができます。そのようです:

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)の間一度だけトラバースされます。

308
Matt Anderson

もしあなたが数のリストの中でmaxのインデックスを見つけたいのなら(それはあなたのケースのようです)、私はあなたがnumpyを使うことを勧めます:

import numpy as np
ind = np.argmax(mylist)
101
dr.haz

おそらくより簡単な解決策は、値の配列を値の配列、インデックスペアに変換し、その最大/最小をとることです。これは、最大/最小を有する最大/最小インデックスを与える(すなわち、最初の要素を最初に比較し、次に最初の要素が同じである場合には2番目の要素を比較することによって対が比較される)。 min/maxはジェネレータを入力として許可するため、実際に配列を作成する必要はありません。

values = [3,4,5]
(m,i) = max((v,i) for i,v in enumerate(values))
print (m,i) #(5, 2)
34
Ant6n
list=[1.1412, 4.3453, 5.8709, 0.1314]
list.index(min(list))

最小のあなたの最初のインデックスを与えます。

26
Andy

私はこれにも興味があり、 perfplot (私のペットプロジェクト)を使って提案された解決策のいくつかを比較しました。

numpy's 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,
    )
11
Nico Schlömer

派手な配列とargmax()関数を使う

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

最大値を得たら、これを試してください。

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

多くのオプションよりもはるかに簡単です。

7
alpha_989

リストをnumpy arrayに変換して次の関数を使うのが一番いいと思います。

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

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])
6
Ishan Tomar

これは、組み込みのenumerate()max()関数、およびmax()関数のオプションのkey引数と単純なラムダ式を使うことで簡単に可能です。

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

max() のドキュメントでは、key引数は list.sort() 関数のように関数を期待すると言っています。 並べ替え方法も参照してください

min()についても同じように機能します。ところでそれは最初の最大/最小値を返します。

4
Simon Hänisch

ラムダと "key"引数の使い方を知っている限り、簡単な解決策は次のとおりです。

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

私は上記の答えがあなたの問題を解決すると思いますが、私はあなたに最小値を与える方法と最小値が現れるすべてのインデックスを共有することを考えていました。

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

これはリストを2回通過しますが、まだかなり高速です。しかし、それは最小の最初の出会いのインデックスを見つけるよりもわずかに遅くなります。それで、あなたが最小値のうちの1つだけを必要とするならば、 Matt Anderson の解決策を使いなさい、あなたがそれらをすべて必要とするなら、これを使いなさい。

4

次のようなリストがあるとしましょう。

a = [9,8,7]

次の2つの方法は、最小要素とそのインデックスを持つTupleを取得するための非常にコンパクトな方法です。どちらも処理に 同様の 時間がかかります。私は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)
4
Pablo MPA

なぜ最初にインデックスを追加し、次にそれらを逆にしたくないのでしょうか。 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)
3
sophist

すでに言われたことへのほんの少しの追加。 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)をキャッシュすることはおそらくより良い考えです。

2
hyperbolic

追加のモジュールをインポートしたくない場合に、リスト内で最小値のインデックスを見つけるための簡単な方法:

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]
2
antoninstuppa

そのような単純な :

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

index = stuff.index(max(stuff))
1
dctremblay

既存の回答にコメントするのに十分な高い担当者を持ってはいけません。

しかし https://stackoverflow.com/a/11825864/3920439 answer

これは整数に対しては動作しますが、float型の配列に対しては動作しません(少なくともPython 3.6では)。TypeError: list indices must be integers or slices, not floatが発生します

1
user3920439

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

複数の項目が最大の場合、この関数は最初に見つかったものを返します。これはsorted(iterable, key=keyfunc, reverse=True)[0]のような他のソート安定性維持ツールと一致しています。

最初のもの以上のものを得るためには、sortメソッドを使用してください。

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)]
0
The Demz