목록에서 max () / min ()을 사용하여 반환 된 최대 또는 최소 항목의 인덱스 가져 오기


465

minimax 알고리즘의 목록에서 Python maxmin함수를 사용 하고 있으며 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)

값뿐만 아니라 최소 또는 최대 값의 실제 색인을 반환 할 수 있어야합니다.


32
많은 divmod말을하지 않기 위해 내장 이 존재합니다 [i / 3, i % 3].
Mike Graham

답변:


416
isMinLevel 인 경우 :
    반환 값. 인덱스 (분 (값))
그밖에:
    반환 값 .index (max (values))

38
@KevinGriffin, 이것은 최소 / 최대 몇 번의 발생 중 하나만 가져옵니다. 예를 들어 같은 두 가지 방법으로 이득을 올릴 수 있지만 그중 하나가 다른 플레이어를 더 아프게하는 경우 이것은 원하는 것이 아닐 수도 있습니다. 이것이 당신이 고려해야 할 경우인지 모르겠습니다.
Mike Graham

89
@Kashyap 실제로 O (N ^ 2)가 아니라 O (N)입니다. 최소의 경우 첫 번째 min (values)이 평가되고 (O (N)) values.index ()가 호출되며 O (N)입니다. O (N) + O (N) = O (N). 인덱스 인수는 한 번만 평가됩니다. : 그것은 동등한이다tmp = min(values); return values.index(tmp)
톰 Karzes

@ 너무 많은 PHP 요소가 반복되면 어떻게해야합니까?
Shashi Tunga

@ShashiTunga [list] .index ()는 무언가의 첫 번째 발생 만 반환합니다. 이것이 독점적 인 것은 아니며 최소값이 목록 내에서 고유하지 않을 수도 있습니다
Scott Anderson

471

list values = [3,6,1,5]가 있고 가장 작은 요소의 인덱스가 필요하다고 가정하십시오 ( index_min = 2이 경우).

itemgetter()다른 답변에 제시된 해결책을 피하고 대신 사용하십시오.

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

import operator를 사용할 필요 도없고 사용할 필요가 없으며를 사용 enumerate하는 솔루션보다 항상 빠릅니다 (아래 벤치 마크) itemgetter().

numpy 배열을 다루거나 numpy종속성으로 감당할 수있는 경우

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

다음과 같은 경우 순수 Python 목록에 적용하더라도 첫 번째 솔루션보다 빠릅니다.

  • 그것은 몇 가지 요소보다 큽니다 (내 기계의 약 2 ** 4 요소)
  • 순수한 목록에서 numpy배열로 메모리 사본을 감당할 수 있습니다

이 벤치 마크가 지적한대로 : 여기에 이미지 설명을 입력하십시오

위의 두 가지 솔루션 (파란색 : 순수한 파이썬, 첫 번째 솔루션) (빨간색, numpy 솔루션) 및 표준 솔루션 itemgetter()(검은 색, 참조 솔루션)에 대해 python 2.7을 사용하여 컴퓨터에서 벤치 마크를 실행했습니다 . python 3.5와 동일한 벤치 마크는 방법이 위에서 제시 한 python 2.7 사례와 정확히 동일하다는 것을 보여주었습니다.


매우 강한 +1. 제안 된 솔루션의 벤치마킹과 요약 한 경험 법칙을 좋아합니다. 아래의 다른 답변에서 제안한 것처럼 다른 사람들이 결과를 재현 할 수 있도록 테스트 코드를 제공하거나 링크 할 수 있습니까? 기계와 라이브러리는 시간이 지남에 따라 변하므로 다른 솔루션과 비교할 수 있습니다.
Rakurai

3
나는 오타가있을 수 있다고 생각합니다 : xrange. 범위가 아니어야합니까?
Lindsay Fowler

6
@LindsayFowler xrange()는 더 이상 사용되지 않으며, 사용할 수 있습니다range()
davide

np.argmin은 수레에서 작동하지 않습니다. 첫 번째 제안 만 ints와 float에 적용됩니다.
jimh

당신이 착각했다고 생각합니다 import numpy as np; x = [2.3, -1.4]; np.argmin(x). argmin수레에서도 작동 한다는 것을 알 수 있습니다
gg349

332

목록의 항목을 열거하지만 목록의 원래 값에 대해 최소 / 최대를 수행하면 최소 / 최대 색인과 값을 동시에 찾을 수 있습니다. 이렇게 :

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

이런 식으로 목록은 최소 (또는 최대) 동안 한 번만 순회됩니다.


110
또는 람다를 사용하십시오 :key=lambda p: p[1]
scry

116

숫자 목록 (최대한 경우)에서 max의 색인을 찾으려면 numpy를 사용하는 것이 좋습니다.

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

최대 값이 여러 번 발생하는 경우 첫 번째 발생에 해당하는 인덱스가 반환됩니다.
코헨 시우스

41

아마도 더 간단한 해결책은 값의 배열을 값의 배열, 인덱스 쌍으로 바꾸고 그 최대 / 최소값을 취하는 것입니다. 이것은 최대 / 최소를 갖는 최대 / 최소 인덱스를 제공합니다 (즉, 첫 번째 요소를 먼저 비교 한 다음 첫 번째 요소가 동일한 경우 두 번째 요소를 비교하여 쌍을 비교합니다). min / max는 제너레이터를 입력으로 허용하기 때문에 실제로 배열을 만들 필요는 없습니다.

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

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

최소의 첫 번째 색인을 제공합니다.


18

가장 좋은 방법은 목록을 a로 변환 numpy array하고이 기능을 사용하는 것입니다.

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

14

나는 이것에 관심이 있었고 perfplot (내 애완 동물 프로젝트)을 사용하여 제안 된 솔루션 중 일부를 비교했습니다 .

numpy의 argmin을 밝혀냅니다 .

numpy.argmin(x)

입력 list에서 a 로의 암시 적 변환에도 불구하고 충분히 큰 목록에 가장 빠른 방법입니다 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,
    )

argmin을 언제 어떻게 사용할 수 있는지에 대한 자세한 정보와 함께 2 년 전에 이미 내 대답에 동일한 결론이 게시되어 있습니다. 동일한 페이지에서 이미 제안 된 내용에 영향을주지 않는 답변을 삭제하는 것이 좋습니다. 비슷한 행동을 위해 SO에 대한 다른 답변을 검토하십시오. 성능 분석에서 최상의 솔루션을 제공하는 실제 답변을 인용하지 않는 것 같습니다. 특히 10K 이상의 담당자가 더 잘 알고있을 정도로 오래 지속 된 사람에게는 다소 나쁩니다.
gg349

@ gg349는 매우 좋은 점이지만 결과를 생성하기위한 소스 코드를 제공하므로 다른 솔루션과 비교하여 쉽게 재현하고 적용 할 수 있습니다. 그는이 답변을 중복으로 제거하는 것을 고려할 수도 있지만 사용한 코드를 포함하거나 연결하여 답변에 가치를 추가 할 수 있습니까?
Rakurai

8

numpy 배열과 argmax () 함수를 사용하십시오.

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

8

최대 값을 얻은 후 다음을 시도하십시오.

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

많은 옵션보다 훨씬 간단합니다.


6

위의 답변이 문제를 해결한다고 생각하지만 최소값과 최소값이 표시되는 방법을 공유한다고 생각했습니다.

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

이것은 목록을 두 번 통과하지만 여전히 매우 빠릅니다. 그러나 최소값의 첫 번째 색인을 찾는 것보다 약간 느립니다. 따라서 최소값 중 하나만 필요하면 Matt Anderson 의 솔루션을 사용하십시오. 모두 필요한 경우 이것을 사용하십시오.


1
이 기본 파이썬을 사용하고, 나는 쉽게 지능형리스트가 itemgetter보다 이해하기 찾을 수 있기 때문에이 같은 나는, 람다 등 (유연한 충분 .... 이와 같은 다양한 작업을 해결하기 위해)
제임스

노골적인. 나는 이것을 선호한다.
Dev_Man

6

numpy 모듈의 함수 numpy를 사용하십시오.

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])

파이썬에서 인덱스는 0에서 시작합니다. 반환 된 인덱스는 6 (65)이고 코드는 7을 반환합니다 (OP의 질문은 "Getting the Index ...")
tagoma

이 명령에서 인덱스 IS 7. 65의 최소값 (여기서는 1)의 인덱스를 쿼리했습니다. 65는 배열 요소의 최대 값입니다. n.where (x == x.max ()) [0]을 입력하면 최대 인덱스가 표시됩니다. 이 값은 65입니다. 이 지수는 6 일 것으로 예상됩니다
Ishan Tomar

numpy 사용 :이 응용 프로그램에서는 금지되어있을 것입니다. 그러나 numpy를 사용하려는 경우 argmin()여기에서 한 작업 대신 사용하는 것이 훨씬 좋습니다 .
RBF06

감사합니다 @ RBF06 확인하겠습니다.
이샨 토 마르

5

이것은 사용하여 간단하게 할 수있는 내장 enumerate()max()기능과 옵션 key의 인수 max()기능과 간단한 람다 식 :

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

문서에서는 인수가 함수와 같은 함수를 기대 max()한다고 말합니다 . 정렬 방법 도 참조하십시오 .keylist.sort()

그것은 동일하게 작동합니다 min(). Btw는 첫 번째 최대 / 최소 값을 반환합니다.


늦었지만 최선의 답변 (속도가 필요없는 경우).
mmj

5

다음과 같은 목록이 있다고 가정하십시오.

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)

4

lambda와 "key"인수를 사용하는 방법을 알고 있다면 간단한 해결책은 다음과 같습니다.

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

매우 깨끗합니다! 그리고 받아 들여진 대답과 달리 이것은 사실입니다 O (n) 맞습니까? 나는 O (2n)이 O (n)으로 간주된다는 것을 알고 있지만 매우 큰 n경우에는 눈에 띄게 느려질 수 있습니다.
kevlarr

4

간단합니다 :

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

index = stuff.index(max(stuff))

3

인덱스를 먼저 추가 한 다음 반대로 바꾸는 이유는 무엇입니까? 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)

2

이미 말한 것에 약간의 추가. values.index(min(values))최소의 최소 지수를 반환하는 것 같습니다. 다음은 가장 큰 색인을 얻습니다.

    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
reversed(…)….reverse()어쨌든 돌연변이를 일으키지 않고 생성기를 반환하기 때문에 대신에 바람직합니다. 그리고 모든 발생도 될 수있다minv = min(values); indices = [i for i, v in enumerate(values) if v == minv]
HoverHell

2

추가 모듈을 가져 오지 않으려는 경우 목록에서 최소한의 값으로 인덱스를 찾는 간단한 방법 :

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]

1

기존 답변에 대해 언급 할만한 담당자가 충분하지 않습니다.

그러나 https : //.com/a/11825864/3920439 대한 답변

이것은 정수에서는 작동하지만 부동 소수점 배열에서는 작동하지 않습니다 (적어도 Python 3.6에서는) TypeError: list indices must be integers or slices, not float


0

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

이건 어때?

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

항목에서 a키로 사전을 작성 하고 해당 색인을 값으로 작성 하여 a의 최대 색인 인 dict(zip(a,range(len(a))))[max(a)]키에 해당하는 값을 리턴합니다 max(a). 나는 파이썬의 초보자 이므로이 솔루션의 계산 복잡성에 대해 모른다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.