목록에서 최대 값의 모든 위치를 찾는 방법은 무엇입니까?


152

나는 목록이있다 :

a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 55, 23, 31, 55, 21, 40, 18, 50,
             35, 41, 49, 37, 19, 40, 41, 31]

최대 요소는 55입니다 (위치 9와 12의 두 요소)

최대 값이 어느 위치에 있는지 찾아야합니다. 도와주세요.

답변:


210
>>> m = max(a)
>>> [i for i, j in enumerate(a) if j == m]
[9, 12]

4
목록을 여러 번 통과하는 것이 마음에 들지 않으면 좋은 대답입니다.
martineau

이것에 대한 큰 0이 2n 인 것을 제외하고,리스트는 최대 값을 결정하기 위해 1 회, 최대 값의 위치를 ​​찾기 위해 2 번 반복된다. 현재 최대 값과 위치를 추적하는 for 루프는 실제로 긴 목록에 더 효율적일 수 있습니다.
radtek

1
@radtek big O는 n입니다. 선행 계수는 큰 O에서 무시됩니다
michaelsnowden

1
이론적으로 O (N)과 O (2N)은 동일하지만 실제로 N (무한대)에 도달 할 때 O (N)의 실행 시간은 확실히 짧습니다.
radtek

314
a.index(max(a))

list의 가장 큰 값을 가진 요소의 첫 번째 인스턴스의 색인을 알려줍니다 a.


8
이렇게하면 첫 번째 인스턴스 만 얻을 수 있으며 가장 큰 값을 찾을 수있는 모든 인덱스를 요청했습니다. 각 경우에 나머지 목록을 가져오고 더 이상 발견되지 않으면 예외를 처리하기 위해 slice를 사용하여 반복해야합니다.
jaydel

10
나는 그것이 첫 번째 사례 만 줄 것이라고 언급했다. 모두 원한다면 SilentGhost의 솔루션은 훨씬 더 예쁘고 오류가 적습니다.
nmichaels

7
적어도 내가 그것에 왔을 때, 질문은 명시 적으로 여러 최대의 경우 목록을 요청합니다 ...
emmagras

2
기술적 으로이 값을 사용하여 가장 큰 값을 가진 요소의 첫 번째 인스턴스를 가져온 다음 엄청나게 큰 음수로 설정 한 다음 다음으로 큰 값을 가진 요소를 찾을 수는 있지만 너무 복잡합니다.
Neil Chowdhury

@nmichaels 허용되는 답변보다 목록에서 최대 가치의 모든 위치를 얻는 가장 좋은 방법이 있습니까?
shaik moeed

18

선택한 답변 (및 대부분의 다른 답변)에는 목록을 통과하는 패스가 두 번 이상 필요합니다.
더 긴 목록에 더 적합한 선택이 될 수있는 원 패스 솔루션이 있습니다.

편집 : @ John Machin이 지적한 두 가지 단점을 해결합니다. (2)에 대해 나는 각 조건의 추정 된 확률과 전임자로부터의 추론에 근거하여 테스트를 최적화하려고 시도했다. 그것은을 위해 적절한 초기 값을 알아내는 조금 신중해야 max_val하고 max_indices최대 목록의 첫 번째 값으로 일어난 특히, 모든 가능한 경우에 근무하는 -하지만 난 지금 않습니다 생각합니다.

def maxelements(seq):
    ''' Return list of position(s) of largest element '''
    max_indices = []
    if seq:
        max_val = seq[0]
        for i,val in ((i,val) for i,val in enumerate(seq) if val >= max_val):
            if val == max_val:
                max_indices.append(i)
            else:
                max_val = val
                max_indices = [i]

    return max_indices

4
(1) 빈 목록 처리에는주의가 필요합니다. []광고 된대로 반환해야합니다 ( "반품 목록"). 코드는 간단해야합니다 if not seq: return []. (2) 루프의 테스트 체계는 차선책입니다. 무작위 목록에서 평균적으로 조건 val < maxval이 가장 일반적이지만 위의 코드는 하나가 아닌 두 가지 테스트를 수행합니다.
John Machin

docstring과 일치하지 않고 차선책을 게시하지 못하게 한 @John Machin의 의견에 +1하십시오. 솔직히 말해서, 답변이 이미 받아 들여 졌기 때문에 나는 더 이상 아무도 그것을 보지 않을 것이라고 가정했기 때문에 내 대답에 대한 작업을 계속하려는 약간의 동기를 잃었습니다. 다른 사람들보다 훨씬 길었습니다.
martineau

1
@martineau : "허용 된"답변이 반드시 "허용 가능한"것은 아닙니다. 나는 일반적으로 모든 답변을 읽습니다. 수정본 포함. 드문 경우이지만 ==2 대신에 3 번의 테스트가 수행 elif됩니다. 조건은 항상 맞습니다.
John Machin

@ John Machin : 나는 정말 영감을 얻었고 더 수정했습니다. 이제 최소한의 추가 테스트와 몇 가지 다른 조정이 내려졌습니다. 귀하의 의견과 건설적인 비판에 감사드립니다. 나는 항상 진실한 elifFWIW를 붙 잡았다 . ;-)
martineau

@ John Machin : 흠, 타이밍 결과가 내 자신과 상충되는 것 같습니다. 따라서 타이밍에 대한 답변에서 내가 말한 것을 제거하여 향후 진행중인 작업을 조사 할 수 있습니다. 헤드 업 주셔서 감사합니다. 실제로 "실제"타이밍 테스트는 임의의 목록 값을 사용해야한다고 생각합니다.
martineau

10

나는 다음을 생각해 냈고 당신이 볼 수 있듯이 작동합니다 max.min 이와 같은 목록을 통해 기능을 다른 사람 :

그래서,의 위치를 찾아 다음 예제 목록을 고려하시기 바랍니다 최대 목록을 a:

>>> a = [3,2,1, 4,5]

발전기 사용 enumerate및 주조

>>> list(enumerate(a))
[(0, 3), (1, 2), (2, 1), (3, 4), (4, 5)]

이 시점에서 우리의 위치를 추출 할 수 있습니다 최대 로를

>>> max(enumerate(a), key=(lambda x: x[1]))
(4, 5)

위의 내용에 따르면 최대 값은 위치 4에 있고 값은 5입니다.

보시다시피, key인수에서 적절한 람다를 정의하여 반복 가능한 객체의 최대 값을 찾을 수 있습니다.

그것이 기여하기를 바랍니다.

PD : @PaulOyster가 의견에서 언급 한 것처럼. 로 및 새 키워드 허용 인상 예외를 피 인수가 빈리스트 인 경우입니다.Python 3.xminmaxdefaultValueErrormax(enumerate(list), key=(lambda x:x[1]), default = -1)


2
단일 패스가 포함되므로 더 나은 솔루션입니다. 그러나 몇 가지 의견 : 1. 열거를 나열 할 필요가 없습니다. 2. 람다는 괄호로 묶는 것이 좋습니다. 3. min () 및 max ()에는 기본 매개 변수가 있습니다 (빈 입력으로 반환 됨). ValueError 예외를 피하려면 (기본값 = 1), 4. 원래 질문이므로 max ()로 변경하십시오.
Paul Oyster

약 3 개의 항목, 그렇습니다 .Python 3.x에서만 작동합니다. 나는 그것을 언급 할 것이다. 그리고 다른 모든 것을 고쳤습니다. ;)
jonaprieto

2
그러면 목록에서 두 번 이상 나타날 때 최대 값이 지정된 요소 중 하나 (첫 번째 요소)의 위치 만 찾을 수 있으므로 질문에 대답하지 않습니다.
martineau

8

@martineau가 인용 한 @ SilentGhost-beating 성능을 재현 할 수 없습니다. 비교를위한 나의 노력은 다음과 같습니다.

=== maxelements.py ===

a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 55, 23, 31, 55, 21, 40, 18, 50,
             35, 41, 49, 37, 19, 40, 41, 31]
b = range(10000)
c = range(10000 - 1, -1, -1)
d = b + c

def maxelements_s(seq): # @SilentGhost
    ''' Return list of position(s) of largest element '''
    m = max(seq)
    return [i for i, j in enumerate(seq) if j == m]

def maxelements_m(seq): # @martineau
    ''' Return list of position(s) of largest element '''
    max_indices = []
    if len(seq):
        max_val = seq[0]
        for i, val in ((i, val) for i, val in enumerate(seq) if val >= max_val):
            if val == max_val:
                max_indices.append(i)
            else:
                max_val = val
                max_indices = [i]
    return max_indices

def maxelements_j(seq): # @John Machin
    ''' Return list of position(s) of largest element '''
    if not seq: return []
    max_val = seq[0] if seq[0] >= seq[-1] else seq[-1]
    max_indices = []
    for i, val in enumerate(seq):
        if val < max_val: continue
        if val == max_val:
            max_indices.append(i)
        else:
            max_val = val
            max_indices = [i]
    return max_indices

Windows XP SP3에서 Python 2.7을 실행하는 구식 노트북의 결과 :

>\python27\python -mtimeit -s"import maxelements as me" "me.maxelements_s(me.a)"
100000 loops, best of 3: 6.88 usec per loop

>\python27\python -mtimeit -s"import maxelements as me" "me.maxelements_m(me.a)"
100000 loops, best of 3: 11.1 usec per loop

>\python27\python -mtimeit -s"import maxelements as me" "me.maxelements_j(me.a)"
100000 loops, best of 3: 8.51 usec per loop

>\python27\python -mtimeit -s"import maxelements as me;a100=me.a*100" "me.maxelements_s(a100)"
1000 loops, best of 3: 535 usec per loop

>\python27\python -mtimeit -s"import maxelements as me;a100=me.a*100" "me.maxelements_m(a100)"
1000 loops, best of 3: 558 usec per loop

>\python27\python -mtimeit -s"import maxelements as me;a100=me.a*100" "me.maxelements_j(a100)"
1000 loops, best of 3: 489 usec per loop

7
a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 
         55, 23, 31, 55, 21, 40, 18, 50,
         35, 41, 49, 37, 19, 40, 41, 31]

import pandas as pd

pd.Series(a).idxmax()

9

그것이 제가 보통하는 방법입니다.


6

numpy 패키지를 사용할 수도 있습니다.

import numpy as np
A = np.array(a)
maximum_indices = np.where(A==max(a))

최대 값을 포함하는 모든 인덱스의 numpy 배열을 반환합니다.

이것을 목록으로 바꾸려면 :

maximum_indices_list = maximum_indices.tolist()

5
>>> max(enumerate([1,2,3,32,1,5,7,9]),key=lambda x: x[1])
>>> (3, 32)

이것은 잘못이다. 목록의 중간에 최대 숫자를 입력하십시오.
goncalopp

1
이것은 잘못이다. 질문은 "최대 값의 모든 위치를 찾으십시오"라고 말합니다.
Kapil

5

또한 첫 번째 모양 만 제공하는 솔루션 은 다음을 사용하여 얻을 수 있습니다 numpy.

>>> import numpy as np
>>> a_np = np.array(a)
>>> np.argmax(a_np)
9

3

@shash 님이 다른 곳에 답변했습니다

최대 목록 요소의 색인을 찾는 Pythonic 방법은 다음과 같습니다.

position = max(enumerate(a), key=lambda x: x[1])[0]

어느 쪽이 통과 합니까 ? 그러나 @Silent_Ghost의 솔루션보다 느리고 @nmichaels보다 느립니다.

for i in s m j n; do echo $i;  python -mtimeit -s"import maxelements as me" "me.maxelements_${i}(me.a)"; done
s
100000 loops, best of 3: 3.13 usec per loop
m
100000 loops, best of 3: 4.99 usec per loop
j
100000 loops, best of 3: 3.71 usec per loop
n
1000000 loops, best of 3: 1.31 usec per loop

2

여기에 최대 값과 그 색인이 나타납니다.

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 55, 23, 31, 55, 21, 40, 18, 50, 35, 41, 49, 37, 19, 40, 41, 31]
>>> for i, x in enumerate(a):
...     d[x].append(i)
... 
>>> k = max(d.keys())
>>> print k, d[k]
55 [9, 12]

나중에 : @SilentGhost의 만족을 위해

>>> from itertools import takewhile
>>> import heapq
>>> 
>>> def popper(heap):
...     while heap:
...         yield heapq.heappop(heap)
... 
>>> a = [32, 37, 28, 30, 37, 25, 27, 24, 35, 55, 23, 31, 55, 21, 40, 18, 50, 35, 41, 49, 37, 19, 40, 41, 31]
>>> h = [(-x, i) for i, x in enumerate(a)]
>>> heapq.heapify(h)
>>> 
>>> largest = heapq.heappop(h)
>>> indexes = [largest[1]] + [x[1] for x in takewhile(lambda large: large[0] == largest[0], popper(h))]
>>> print -largest[0], indexes
55 [9, 12]

이것이 얼마나 비효율적인지 알고 있습니까?
SilentGhost

1
합리화 : (1) "조기 최적화는 ... 등입니다." (2) 아마 중요하지 않습니다. (3) 여전히 좋은 해결책입니다. 어쩌면 나는 그것을 사용하도록 코딩 할 heapq것입니다. 사소한 최대 값을 찾는 것이 좋습니다.
hughdbrown

귀하의 heapq솔루션 을보고 싶지만 그것이 효과가 있을지는 의문입니다.
SilentGhost

2

목록 이해가 있지만 열거가없는 비슷한 아이디어

m = max(a)
[i for i in range(len(a)) if a[i] == m]

나는 downvoter는 아니지만 이것이 실제로 멋지게 보이지 않고 잘 수행되지 않는다는 점에 유의하십시오. 목록을 통해 대신 인덱스를 반복하는 것은 Python에서 매우 어색합니다.이를 피하려고합니다. 또한 a[i]호출 때문에 열거 형이있는 솔루션보다 확실히 느립니다 .
yo '

1

한 줄만 :

idx = max(range(len(a)), key = lambda i: a[i])

좋지만 모든 인덱스를 반환하지는 않으며 첫 번째 인덱스 만 반환합니다.
돼지

1

n이라는 목록에서 가장 큰 숫자 의 인덱스를 얻으려면 dataPandas를 사용할 수 있습니다 sort_values.

pd.Series(data).sort_values(ascending=False).index[0:n]

0
import operator

def max_positions(iterable, key=None, reverse=False):
  if key is None:
    def key(x):
      return x
  if reverse:
    better = operator.lt
  else:
    better = operator.gt

  it = enumerate(iterable)
  for pos, item in it:
    break
  else:
    raise ValueError("max_positions: empty iterable")
    # note this is the same exception type raised by max([])
  cur_max = key(item)
  cur_pos = [pos]

  for pos, item in it:
    k = key(item)
    if better(k, cur_max):
      cur_max = k
      cur_pos = [pos]
    elif k == cur_max:
      cur_pos.append(pos)

  return cur_max, cur_pos

def min_positions(iterable, key=None, reverse=False):
  return max_positions(iterable, key, not reverse)

>>> L = range(10) * 2
>>> L
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> max_positions(L)
(9, [9, 19])
>>> min_positions(L)
(0, [0, 10])
>>> max_positions(L, key=lambda x: x // 2, reverse=True)
(0, [0, 1, 10, 11])

0

이 코드는 이전에 게시 된 답변만큼 정교하지는 않지만 작동합니다.

m = max(a)
n = 0    # frequency of max (a)
for number in a :
    if number == m :
        n = n + 1
ilist = [None] * n  # a list containing index values of maximum number in list a.
ilistindex = 0
aindex = 0  # required index value.    
for number in a :
    if number == m :
        ilist[ilistindex] = aindex
        ilistindex = ilistindex + 1
    aindex = aindex + 1

print ilist

위의 코드에서 ilist 는 목록에서 최대 숫자의 모든 위치를 포함합니다.


0

다양한 방법으로 할 수 있습니다.

옛날 방식은

maxIndexList = list() #this list will store indices of maximum values
maximumValue = max(a) #get maximum value of the list
length = len(a)       #calculate length of the array

for i in range(length): #loop through 0 to length-1 (because, 0 based indexing)
    if a[i]==maximumValue: #if any value of list a is equal to maximum value then store its index to maxIndexList
        maxIndexList.append(i)

print(maxIndexList) #finally print the list

목록의 길이를 계산하지 않고 변수에 최대 값을 저장하지 않는 다른 방법,

maxIndexList = list()
index = 0 #variable to store index
for i in a: #iterate through the list (actually iterating through the value of list, not index )
    if i==max(a): #max(a) returns a maximum value of list.
        maxIndexList.append(index) #store the index of maximum value
index = index+1 #increment the index

print(maxIndexList)

우리는 파이썬적이고 똑똑한 방법으로 그것을 할 수 있습니다! 한 줄로만 목록 이해력을 사용하면

maxIndexList = [i for i,j in enumerate(a) if j==max(a)] #here,i=index and j = value of that index

모든 코드는 Python 3에 있습니다.

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