2012-03-14 11 views
39

A titolo di esempio la mia lista è:indice di ritrovamento di un elemento più vicino al valore in un elenco che non è del tutto allineati

[25.75443, 26.7803, 25.79099, 24.17642, 24.3526, 22.79056, 20.84866, 19.49222, 18.38086, 18.0358, 16.57819, 15.71255, 14.79059, 13.64154, 13.09409, 12.18347, 11.33447, 10.32184, 9.544922, 8.813385, 8.181152, 6.983734, 6.048035, 5.505096, 4.65799] 

e non vedo per l'indice del valore più vicino a 11.5. Ho provato altri metodi come la ricerca binaria e bisect_left ma non funzionano.

Non riesco a ordinare questo array, perché l'indice del valore verrà utilizzato su un array simile per recuperare il valore in quell'indice.

+2

Possibile duplicato di [dall'elenco di numeri interi, ottieni il numero più vicino a un valore specificato] (https: // stackoverflow.it/questions/12141150/from-list-of-interi-get-number-closest-to-a-a-valore-dato) –

risposta

100

provare quanto segue:

min(range(len(a)), key=lambda i: abs(a[i]-11.5)) 

Ad esempio:

>>> a = [25.75443, 26.7803, 25.79099, 24.17642, 24.3526, 22.79056, 20.84866, 19.49222, 18.38086, 18.0358, 16.57819, 15.71255, 14.79059, 13.64154, 13.09409, 12.18347, 11.33447, 10.32184, 9.544922, 8.813385, 8.181152, 6.983734, 6.048035, 5.505096, 4.65799] 
>>> min(range(len(a)), key=lambda i: abs(a[i]-11.5)) 
16 

O per ottenere l'indice e il valore:

>>> min(enumerate(a), key=lambda x: abs(x[1]-11.5)) 
(16, 11.33447) 
2

Che ne dici di: zippare le due liste, quindi ordinare il risultato?

+0

@GhassenLouhaichi Non c'è nessun collegamento in questo post. Si prega di pensare prima di pubblicare un commento automatico. –

2

Se non è possibile ordinare l'array, quindi non c'è un modo rapido per trovare l'oggetto più vicino - devi ripetere tutte le voci.

C'è una soluzione, ma è un po 'di lavoro: Scrivere un algoritmo di ordinamento che ordina l'array e (allo stesso tempo) aggiorna un secondo array che ti dice dove questa voce è stata prima l'array è stato risolto.

In questo modo, è possibile utilizzare la ricerca binaria per cercare l'indice della voce più vicina e quindi utilizzare questo indice per cercare l'indice originale utilizzando la "serie di indici".

[EDIT] Utilizzando zip(), questo è abbastanza semplice da realizzare:

array_to_sort = zip(original_array, range(len(original_array))) 
array_to_sort.sort(key=i:i[0]) 

Ora è possibile ricerca binaria per il valore (usando item[0]). item[1] ti darà l'indice originale.

2

L'attraversamento di tutte le voci è solo lineare. Se ordinassi la matrice, sarebbe peggio.

Non vedo un problema nel mantenere un ulteriore deltax (la differenza minima fino ad ora) e idx (l'indice di quell'elemento) e solo un ciclo una volta attraverso l'elenco.

1

Ricordare che se lo spazio non è importante, è possibile ordinare qualsiasi elenco senza spostare i contenuti creando un elenco secondario degli indici ordinati.

Inoltre, tenere presente che se si sta eseguendo questa ricerca solo una volta, sarà sufficiente attraversare ogni elemento nell'elenco O (n). (Se più volte allora probabilmente vorrebbe ordinare per aumentare l'efficienza in seguito)

0
import numpy as np 

a = [25.75443, 26.7803, 25.79099, 24.17642, 24.3526, 22.79056, 20.84866, 19.49222, 18.38086, 18.0358, 16.57819, 15.71255, 14.79059, 13.64154, 13.09409, 12.18347, 11.33447, 10.32184, 9.544922, 8.813385, 8.181152, 6.983734, 6.048035, 5.505096, 4.65799] 

index = np.argmin(np.abs(np.array(a)-11.5)) 
a[index] # here is your result 

Nel caso in cui a è già una matrice, la corrispondente trasformazione può essere omesso.

Problemi correlati