Bagaimana menemukan semua posisi dengan nilai maksimum dalam daftar?

152

Saya punya daftar:

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]

elemen maks adalah 55 (dua elemen pada posisi 9 dan 12)

Saya perlu mencari di posisi mana nilai maksimum berada. Tolong bantu.

Bob
sumber

Jawaban:

210
>>> m = max(a)
>>> [i for i, j in enumerate(a) if j == m]
[9, 12]
SilentGhost
sumber
4
Jawaban singkat yang bagus jika Anda tidak keberatan membuat banyak melewati daftar - yang mungkin.
martineau
Kecuali 0 besar untuk ini adalah 2n, daftar diulangi 2x, satu kali untuk menentukan maks, dan waktu lain untuk menemukan posisi maks. A untuk loop yang melacak maks saat ini dan posisinya mungkin lebih efisien untuk daftar yang sangat panjang.
radtek
1
@radtek big O hanya n. koefisien terkemuka diabaikan dalam O
michaelsnowden
1
Secara teoritis O (N) dan O (2N) adalah sama tetapi tetapi secara praktis, O (N) pasti akan memiliki waktu berjalan lebih pendek, terutama ketika N mendekati tak terhingga.
radtek
314
a.index(max(a))

akan memberi tahu Anda indeks instance pertama dari elemen daftar bernilai terbesar a.

nmichaels
sumber
8
Ini hanya akan memberi Anda contoh pertama dan dia meminta semua indeks di mana nilai terbesar ditemukan. Anda harus mengulanginya menggunakan slice untuk mendapatkan daftar yang tersisa di setiap case dan menangani pengecualian ketika tidak ditemukan lagi.
jaydel
10
Saya memang menyebutkan bahwa itu hanya akan memberikan contoh pertama. Jika Anda menginginkan semuanya, solusi SilentGhost jauh lebih cantik dan lebih rentan kesalahan.
nmichaels
7
Setidaknya ketika saya sampai di sana, pertanyaan itu secara eksplisit meminta daftar dalam hal beberapa maksima ...
emmagras
2
Secara teknis, Anda bisa menggunakan ini untuk mendapatkan contoh pertama dari elemen bernilai terbesar dan kemudian mengaturnya ke angka negatif yang sangat besar, dan kemudian menemukan elemen bernilai terbesar berikutnya, tetapi itu akan terlalu kompleks.
Neil Chowdhury
@nmichaels Apakah ada cara terbaik untuk mendapatkan semua posisi dengan nilai maksimal dalam daftar selain jawaban yang diterima?
shaik moeed
18

Jawaban yang dipilih (dan sebagian besar lainnya) memerlukan setidaknya dua melewati daftar.
Inilah solusi satu lulus yang mungkin menjadi pilihan yang lebih baik untuk daftar yang lebih panjang.

Diedit: Untuk mengatasi dua kekurangan yang ditunjukkan oleh @John Machin. Untuk (2) saya mencoba untuk mengoptimalkan tes berdasarkan probabilitas dugaan kemunculan dari setiap kondisi dan kesimpulan yang diizinkan dari para pendahulu. Agak sulit mencari tahu nilai inisialisasi yang tepat untuk max_valdan max_indicesyang bekerja untuk semua kasus yang mungkin, terutama jika maks kebetulan adalah nilai pertama dalam daftar - tapi saya percaya sekarang melakukannya.

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
martineau
sumber
4
(1) Penanganan daftar kosong perlu mendapat perhatian. Harus kembali []seperti yang diiklankan ("Daftar pengembalian "). Kode harus sederhana if not seq: return []. (2) Skema pengujian dalam loop adalah sub-optimal: rata-rata dalam daftar acak, kondisi val < maxvalakan menjadi yang paling umum tetapi kode di atas mengambil 2 tes, bukan satu.
John Machin
+1 ke @John Machin komentar untuk menangkap inkonsistensi dengan docstring dan tidak membiarkan saya lolos dengan memposting kode sub-optimal. Sejujurnya, karena jawaban sudah diterima, saya kehilangan sedikit motivasi untuk terus mengerjakan jawaban saya, karena saya berasumsi hampir tidak ada orang yang bahkan akan melihatnya - dan itu jauh lebih lama daripada jawaban orang lain.
martineau
1
@martineau: jawaban "diterima" belum tentu "dapat diterima". Saya biasanya membaca semua jawaban. Termasuk revisi Anda. Yang melakukan 3 tes sekarang dalam kasus yang jarang, ==bukan 2 - elifkondisi Anda akan selalu benar.
John Machin
@ John Machin: Saya benar-benar terinspirasi dan merevisinya lebih jauh. Sekarang turun tes tambahan minimum, ditambah beberapa tweak lainnya. Terima kasih atas komentar dan kritik membangun Anda. Saya menangkap selalu True elifsendiri, FWIW. ;-)
martineau
@ John Machin: Hmmm, hasil waktu Anda tampaknya bertentangan dengan saya sendiri, jadi saya akan menghapus apa yang saya katakan dalam jawaban saya tentang waktu sehingga saya dapat melihat apa yang terjadi selanjutnya. Terimakasih atas peringatannya. Sebenarnya saya pikir tes waktu "nyata" perlu menggunakan nilai daftar acak.
martineau
10

Saya datang dengan yang berikut dan berfungsi seperti yang Anda lihat max, mindan yang lain berfungsi di daftar seperti ini:

Jadi, harap pertimbangkan contoh daftar berikut ini untuk mengetahui posisi maksimum dalam daftar a:

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

Menggunakan generator enumerate dan membuat casting

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

Pada titik ini, kita dapat mengekstraksi posisi max dengan

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

Di atas memberitahu kita, maksimum ada di posisi 4 dan nilainya 5.

Seperti yang Anda lihat, dalam keyargumen, Anda dapat menemukan maksimum di atas objek yang dapat diulang dengan mendefinisikan lambda yang sesuai.

Saya harap ini berkontribusi.

PD: Seperti yang dicatat oleh @PaulOyster dalam komentar. Dengan Python 3.xyang mindan maxmemungkinkan kata kunci baru defaultyang menghindari pengecualian kenaikan ValueErrorketika argumen adalah daftar kosong.max(enumerate(list), key=(lambda x:x[1]), default = -1)

Jonaprieto
sumber
2
Ini adalah solusi yang lebih baik, karena melibatkan satu lintasan. Beberapa komentar, meskipun: 1. tidak perlu daftar () enumerasi, 2. lambda lebih baik dipasangkan, 3. min () dan maks () sekarang memiliki parameter default (yang dikembalikan pada input kosong), sehingga dapat menggunakan itu (default = -1, misalnya) untuk menghindari pengecualian ValueError, dan 4. tolong ubah ke maks (), karena ini adalah pertanyaan asli.
Paul Oyster
sekitar 3 item, ya, itu hanya berfungsi dengan Python 3.x. Saya akan menyebutkan itu. Dan memperbaiki yang lainnya. ;)
jonaprieto
2
Ini hanya akan menemukan posisi salah satu elemen bernilai maksimum (yang pertama) ketika muncul lebih dari satu kali dalam daftar — jadi jangan jawab pertanyaan yang diajukan.
martineau
8

Saya tidak dapat mereproduksi kinerja pemukulan @ SilentGhost yang dikutip oleh @martineau. Inilah upaya saya dengan perbandingan:

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

Hasil dari laptop lama usang yang menjalankan Python 2.7 pada Windows XP SP3:

>\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
John Machin
sumber
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

Begitulah biasanya saya melakukannya.

Arijit Laha
sumber
6

Anda juga dapat menggunakan paket numpy:

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

Ini akan mengembalikan array numpy dari semua indeks yang berisi nilai maks

jika Anda ingin mengubah ini menjadi daftar:

maximum_indices_list = maximum_indices.tolist()
pengguna3569257
sumber
5
>>> max(enumerate([1,2,3,32,1,5,7,9]),key=lambda x: x[1])
>>> (3, 32)
Hari Roshan
sumber
Ini salah. Coba letakkan angka maksimum di tengah daftar.
goncalopp
1
Ini salah. Pertanyaan mengatakan "temukan semua posisi dengan nilai maksimum".
Kapil
5

Juga solusi, yang memberi hanya penampilan pertama , dapat dicapai dengan menggunakan numpy:

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

@shash menjawab ini di tempat lain

Cara Pythonic untuk menemukan indeks elemen daftar maksimum adalah

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

Yang satu lulus . Namun, ini lebih lambat daripada solusi oleh @Silent_Ghost dan, lebih dari itu, @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
serv-inc
sumber
2

Berikut adalah nilai maks dan indeks yang muncul di:

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

Kemudian: untuk kepuasan @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]
hughdbrown
sumber
Anda menyadari betapa tidak efisiennya ini?
SilentGhost
1
Rasionalisasi: (1) "Optimalisasi prematur adalah ... dll." (2) Mungkin tidak masalah. (3) Itu masih solusi yang bagus. Mungkin saya akan mengode ulang untuk menggunakan heapq- menemukan max akan ada sepele.
hughdbrown
sementara saya ingin melihat heapqsolusi Anda , saya ragu itu akan berhasil.
SilentGhost
2

Gagasan serupa dengan pemahaman daftar tetapi tanpa menyebutkan

m = max(a)
[i for i in range(len(a)) if a[i] == m]
Salvador Dali
sumber
Saya bukan downvoter, tetapi perhatikan bahwa ini tidak terlihat bagus dan tidak akan berkinerja baik: iterasi melalui indeks bukan melalui daftar sangat canggung dalam Python, Anda mencoba untuk menghindari ini. Juga, itu pasti lebih lambat daripada solusi dengan menghitung karena a[i]panggilan.
yo '
1

Hanya satu baris:

idx = max(range(len(a)), key = lambda i: a[i])
divkakwani
sumber
Bagus, tetapi itu tidak mengembalikan SEMUA indeks, hanya yang pertama.
iggy
1

Jika Anda ingin mendapatkan indeks nangka terbesar dalam daftar yang dipanggil data, Anda dapat menggunakan Pandas sort_values:

pd.Series(data).sort_values(ascending=False).index[0:n]
dannyg
sumber
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])

sumber
0

Kode ini tidak secanggih jawaban yang diposting sebelumnya tetapi akan berfungsi:

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

daftar dalam kode di atas akan berisi semua posisi dari jumlah maksimum dalam daftar.

Sukrit Gupta
sumber
0

Anda dapat melakukannya dengan berbagai cara.

Cara konvensional yang lama adalah,

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

Cara lain tanpa menghitung panjang daftar dan menyimpan nilai maksimum ke variabel apa pun,

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)

Kita bisa melakukannya dengan Pythonic dan cara yang cerdas! Menggunakan pemahaman daftar hanya dalam satu baris,

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

Semua kode saya dalam Python 3.

Islam Taohidul
sumber