私はミニマックスアルゴリズムのためにリスト上でPythonのmax
とmin
関数を使っています、そして私は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)
値だけでなく、最小値または最大値の実際のインデックスを返すことができる必要があります。
if isMinLevel: 戻り値.index(min(values)) else: 戻り値.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
を買う余裕があるならば、また使用を検討してください。
import numpy as np
index_min = np.argmin(values)
次のような場合に純粋なPythonリストに適用しても、これは最初の解決策よりも速くなります。
numpy
配列へのメモリコピーが可能です。上記の2つの解決策(青:純粋なpython、最初の解決策)(赤、派手な解決策)とitemgetter()
に基づく標準解決策(黒、参照解決策)について、私は自分のマシンでpython 2.7を使ってベンチマークを実行しました。 python 3.5と同じベンチマークでは、これらのメソッドは上記のpython 2.7の場合とまったく同じであることがわかりました。
リスト内の項目を列挙しても、リストの元の値に対して最小/最大を実行すると、最小/最大インデックスと値を同時に見つけることができます。そのようです:
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)
おそらくより簡単な解決策は、値の配列を値の配列、インデックスペアに変換し、その最大/最小をとることです。これは、最大/最小を有する最大/最小インデックスを与える(すなわち、最初の要素を最初に比較し、次に最初の要素が同じである場合には2番目の要素を比較することによって対が比較される)。 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's 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,
)
派手な配列と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)
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])
これは、組み込みの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()
についても同じように機能します。ところでそれは最初の最大/最小値を返します。
ラムダと "key"引数の使い方を知っている限り、簡単な解決策は次のとおりです。
max_index = max( range( len(my_list) ), key = lambda index : my_list[ index ] )
私は上記の答えがあなたの問題を解決すると思いますが、私はあなたに最小値を与える方法と最小値が現れるすべてのインデックスを共有することを考えていました。
minval = min(mylist)
ind = [i for i, v in enumerate(mylist) if v == minval]
これはリストを2回通過しますが、まだかなり高速です。しかし、それは最小の最初の出会いのインデックスを見つけるよりもわずかに遅くなります。それで、あなたが最小値のうちの1つだけを必要とするならば、 Matt Anderson の解決策を使いなさい、あなたがそれらをすべて必要とするなら、これを使いなさい。
次のようなリストがあるとしましょう。
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)
なぜ最初にインデックスを追加し、次にそれらを逆にしたくないのでしょうか。 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))
既存の回答にコメントするのに十分な高い担当者を持ってはいけません。
しかし https://stackoverflow.com/a/11825864/3920439 answer
これは整数に対しては動作しますが、float型の配列に対しては動作しません(少なくとも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]
のような他のソート安定性維持ツールと一致しています。
最初のもの以上のものを得るためには、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)]