Fondamentalmente devi fare un argsort, quale implementazione ti serve se vuoi usare librerie esterne (es. NumPy) o se vuoi rimanere pure-Python senza dipendenze.
La domanda che devi porti è: vuoi il
- indici che ordinerebbero la matrice / lista
- indici che gli elementi avrebbero nella matrice / lista ordinata
Sfortunatamente l'esempio nella domanda non chiarisce ciò che si desidera perché entrambi daranno lo stesso risultato:
>>> arr = np.array([1, 2, 3, 100, 5])
>>> np.argsort(np.argsort(arr))
array([0, 1, 2, 4, 3], dtype=int64)
>>> np.argsort(arr)
array([0, 1, 2, 4, 3], dtype=int64)
Scelta argsortdell'implementazione
Se hai NumPy a tua disposizione, puoi semplicemente utilizzare la funzione numpy.argsorto il metodo numpy.ndarray.argsort.
Un'implementazione senza NumPy è già stata menzionata in alcune altre risposte, quindi ricapitolerò la soluzione più veloce in base alla risposta del benchmark qui
def argsort(l):
return sorted(range(len(l)), key=l.__getitem__)
Ottenere gli indici che ordinerebbero la matrice / lista
Per ottenere gli indici che ordinerebbero l'array / list, puoi semplicemente chiamare argsortl'array o l'elenco. Sto usando le versioni di NumPy qui, ma l'implementazione di Python dovrebbe dare gli stessi risultati
>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(arr)
array([1, 2, 0, 3], dtype=int64)
Il risultato contiene gli indici necessari per ottenere l'array ordinato.
Poiché la matrice ordinata sarebbe [1, 2, 3, 4]la matrice argsorted contiene gli indici di questi elementi nell'originale.
- Il valore più piccolo è
1ed è all'indice 1dell'originale, quindi il primo elemento del risultato è 1.
- L'
2indice è 2nell'originale, quindi il secondo elemento del risultato è 2.
- L'
3indice è 0nell'originale quindi il terzo elemento del risultato è 0.
- Il valore più grande
4ed è all'indice 3dell'originale, quindi l'ultimo elemento del risultato è 3.
Ottenere gli indici che gli elementi avrebbero nella matrice / lista ordinata
In questo caso dovrai applicare argsort due volte :
>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(np.argsort(arr))
array([2, 0, 1, 3], dtype=int64)
In questo caso :
- il primo elemento dell'originale è
3, che è il terzo valore più grande, quindi dovrebbe essere indicizzato 2nella matrice / lista ordinata, quindi il primo elemento è 2.
- il secondo elemento dell'originale è
1, che è il valore più piccolo, quindi dovrebbe essere indicizzato 0nella matrice / lista ordinata, quindi il secondo elemento è 0.
- il terzo elemento dell'originale è
2, che è il secondo valore più piccolo, quindi avrebbe l'indice 1nella matrice / lista ordinata, quindi il terzo elemento è 1.
- il quarto elemento dell'originale è
4il valore più grande, quindi dovrebbe essere indicizzato 3nella matrice / lista ordinata, quindi l'ultimo è 3.