2012-06-28 9 views

risposta

33

Poiché si sa già come trovare il valore minimo, è sufficiente alimentare tale valore alla funzione index() per ottenere l'indice di questo valore nell'elenco. Cioè,

n = [20, 15, 27, 30] 
n.index(min(n)) 

cede

1 

Ciò restituirà l'indice del valore minimo nella lista. Si noti che se ci sono diversi minimi restituirà il prima.

min(): Con un singolo argomento iterabile, restituisce l'elemento più piccolo di un valore iterabile non vuoto (ad esempio una stringa, una tupla o un elenco). Con più di un argomento, restituisci il più piccolo degli argomenti.

list.index(x): Restituisce l'indice nella lista della voce prima il cui valore è x. È un errore se non esiste tale elemento.

7

Un'altra opzione a seconda della complessità dei dati:

import heapq 
s = [20, 15, 27, 30] 
heapq.nsmallest(1, ((k, i) for i, k in enumerate(s))) 
+1

Questo è (probabilmente) più veloce in generale, perché il più noto caso peggiore complessità legata per la costruzione di un heap è O (n), mentre il confronto gli ordinamenti hanno un limite di caso peggiore O (nlog (n)). Tuttavia, sarebbe comunque opportuno profilare le due implementazioni per garantire che le implementazioni Python di queste strutture dati siano coerenti con i migliori limiti del caso. – mvanveen

+0

Mi piace perché funzionerebbe su un iteratore. – steveha

10
>>> L = [20, 15, 27, 30] 
>>> min(range(len(L)), key=L.__getitem__) 
1 
5

Questo è simile alla risposta di @ Jon Clements. Il suo uso è heapq il che significa che può essere utilizzato per trovare più di un valore minimo. Invece di usare itemgetter(), inverte semplicemente l'ordine dei valori nelle tuple in modo che siano naturalmente ordinati nell'ordine corretto.

Se tutto ciò che serve è il singolo più piccolo valore, questo è un modo semplice:

from operator import itemgetter 
lst = [20, 15, 27, 30] 
i, value = min(enumerate(lst), key=itemgetter(1)) 

enumerate() è il solito modo in Python per accoppiare i valori da un elenco e loro indici; restituisce un iteratore che produce tuple come (i, value) dove value è un valore della sequenza originale e i è l'indice di tale valore all'interno della sequenza. min() può eseguire un iteratore; l'argomento key= è impostato su una funzione che ignora il valore dell'indice accoppiato e trova solo il secondo valore minimo (indice 1) all'interno di ciascuna tupla.

min() restituisce la tupla che trova con il valore minimo e quindi usiamo la decompressione tupla per assegnare i valori a i e value.

L'esempio mostrato è una lista, ma questo dovrebbe funzionare con qualsiasi sequenza tra cui un iteratore:

from random import randint 
def rseq(n=20): 
    for i in xrange(n): 
     yield randint(0, 101) 

i, value = min(enumerate(rseq()), key=itemgetter(1)) 

Nota che itemgetter(n) è una fabbrica che rende gli oggetti richiamabili. Con itemgetter(1) si ottiene un callable che restituisce il secondo elemento (indice 1) in una sequenza (in questo caso, una tupla).Si potrebbe anche scrivere una funzione o una funzione lambda a fare la stessa cosa:

def get1(x): 
    return x[1] 
i, value = min(enumerate(lst), key=get1) 

i, value = min(enumerate(lst), key=lambda x: x[1]) 
+0

E ovviamente, usando 'itemgetter' (almeno in CPython) prende l'esecuzione del codice da Python e nel livello C. –

+0

@ Jon Clements, mi chiedo se sarebbe più veloce costruire semplicemente le tuple in ordine inverso, come ha fatto la tua risposta. – steveha

+2

Dubito che la performance sarebbe/dovrebbe essere un collo di bottiglia significativamente diverso - anche se sono stato corretto prima. Prendendo un po 'di codice da 1 mese per eseguire a 3 giorni - Sono contento. Dare fastidio un po 'che va da 2mins54s a 2mins30 - Non posso essere disturbato con - Non sto operando sistemi ospedalieri, e sono IO legato comunque, quindi :) –

Problemi correlati