リスト内の最大値のすべての位置を見つける方法は?


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に2つの要素)

最大値が配置されている位置を見つける必要があります。助けてください。

回答:


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

4
リストを複数回パスすることを気にしない場合の良い短い回答-可能性が高いです。
martineau

これの大きな0が2nであることを除いて、リストは2xを介して反復され、1回は最大を決定し、もう1回は最大の位置を見つけます。現在の最大値とその位置を追跡するforループは、本当に長いリストの場合により効率的かもしれません。
radtek、2015年

1
@radtekビッグOはちょうどnです。ビッグOでは、先行係数は無視されます
マイケルズノーデン、2015年

1
理論的にはO(N)とO(2N)は同じですが、特にNが無限大に近づくにつれて、O(N)の実行時間は明らかに短くなります。
radtek、2015年

314
a.index(max(a))

listの最大の値を持つ要素の最初のインスタンスのインデックスを教えてくれますa


8
ただし、これは最初のインスタンスのみを取得し、最大の値が見つかったすべてのインデックスを要求しました。それぞれの場合で残りのリストを取得し、それが検出されなくなったときに例外を処理するには、スライスを使用してループする必要があります。
ジェイデル

10
最初のインスタンスのみを提供することは述べました。これらすべてが必要な場合、SilentGhostのソリューションははるかに美しく、エラーが発生しにくくなります。
nmichaels

7
少なくとも私がそれに
到達

2
技術的には、これを使用して最大値の要素の最初のインスタンスを取得し、それを途方もなく大きい負の数に設定してから、次に大きい値の要素を見つけることができますが、これは複雑すぎます。
Neil Chowdhury 2017年

@nmichaels受け入れられた回答よりもリスト内の最大値のすべての位置を取得する最善の方法はありますか?
Shaik moeed

18

選択した回答(および他のほとんどの回答)では、リストを少なくとも2回通過する必要があります。
これは、より長いリストに適したワンパスソリューションです。

編集: @John Machinによって指摘された2つの欠陥に対処するため。(2)については、各条件の発生の推定された確率と、前任者から許可された推論に基づいて、テストを最適化しようとしました。それはのために適切な初期値を考え出す少しトリッキーだったmax_valmax_indicesmaxのは、リストの最初の値であることを起こっ場合は特に、すべての可能な場合のために働いている-私はそれが今ないと信じています。

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はありません。ランダムリストでは平均して条件が最も一般的ですが、上記のコードは1つではなく2つのテストを行います。
John Machin

@John Machinのコメントに+1して、docstringとの不整合をキャッチし、次善のコードの投稿を回避できないようにします。正直に言うと、回答は既に受け入れられていたため、他の誰もそれを見る人はほとんどいないだろうと思っていたため、私の回答に取り組み続ける動機が少し失われました。
martineau

1
@martineau:「承認された」回答は必ずしも「承認された」とは限りません。私は一般的にすべての答えを読みます。リビジョンを含みます。まれ==に2ではなく3つのテストelifが実行されます。条件は常にtrueになります。
John Machin

@John Machin:私は本当にインスピレーションを得て、それをさらに修正しました。これで、最低限の追加テストに加えて、その他のいくつかの調整が行われました。あなたのコメントと建設的な批判をありがとう。私はいつも本当のelif自分を捕まえた、FWIW。;-)
マルティノー

@John Machin:うーん、あなたのタイミング結果は私自身の結果と矛盾しているようですので、タイミングについての私の答えで私が言ったことを削除して、さらに何が起こっているのか調査できるようにします。ヘッドアップをありがとう。実際、「実際の」タイミングテストでは、ランダムなリスト値を使用する必要があると思います。
martineau

10

私は次のように上がってきたあなたが見ることができるようにそれが動作しmaxminこのようなリストの上に、その他の機能:

したがって、次のリストの例で、リスト内の最大値の位置を確認してください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.列挙をlist()する必要がない、2。ラムダを括弧でくくる、3。min()とmax()にデフォルトのパラメーター(空の入力で返される)があるため、 ValueError例外を回避するためにそれ(デフォルトは-1)、4。これは元の質問だったので、max()に変更してください。
Paul Oyster

約3アイテム、はい、それはPython 3.xで動作します。それについてお話しします。そして、他のすべてを修正しました。;)
jonaprieto 2015年

2
これは、リスト内で複数回出現する場合に、最大値の要素(最初の要素)の1つだけの位置を見つけるため、尋ねられた質問には答えません。
martineau 2018年

8

@martineauが引用している@SilentGhostを上回るパフォーマンスを再現できません。これが比較による私の努力です:

=== 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 2016年

1
これは間違っています。質問は「最大値のすべての位置を見つける」と言います。
カピル2018年

5

また、最初の外観のみを提供するソリューションは、以下を使用して実現できますnumpy

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

3

@shashが他の場所でこれに回答しました

最大のリスト要素のインデックスを見つけるためのPythonの方法は

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]

私はダウンボーターではありませんが、これは見栄えがよくなく、パフォーマンスもよくないことに注意してください。リストではなくインデックスを反復するのは、Pythonでは非常に扱いにくいので、これを回避しようとします。また、a[i]呼び出しのため、enumerateを使用したソリューションよりも確実に遅くなります。
よ '

1

たった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)

Pythonicicでスマートな方法でそれを行うことができます!リスト内包表記を1行で使用すると、

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.