J'ai une liste numérique:
myList = [1, 2, 3, 100, 5]
Maintenant, si je trie cette liste pour obtenir [1, 2, 3, 5, 100]
. Ce que je veux, ce sont les index des éléments de la liste d'origine dans l'ordre de tri, c'est-à-dire [0, 1, 2, 4, 3]
--- ala fonction de tri de MATLAB qui renvoie les valeurs et les index.
Si vous utilisez numpy, vous avez la fonction argsort () disponible:
>>> import numpy
>>> numpy.argsort(myList)
array([0, 1, 2, 4, 3])
http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
Ceci retourne les arguments qui trieraient le tableau ou la liste.
Quelque chose comme:
>>> myList = [1, 2, 3, 100, 5]
>>> [i[0] for i in sorted(enumerate(myList), key=lambda x:x[1])]
[0, 1, 2, 4, 3]
enumerate(myList)
vous donne une liste contenant des nuplets de (index, valeur):
[(0, 1), (1, 2), (2, 3), (3, 100), (4, 5)]
Vous triez la liste en la passant à sorted
et en spécifiant une fonction pour extraire la clé de tri (le deuxième élément de chaque tuple; c'est à cela que sert le lambda
. Enfin, l'index d'origine de chaque - trié l'élément est extrait à l'aide de la compréhension de la liste [i[0] for i in ...]
.
myList = [1, 2, 3, 100, 5]
sorted(range(len(myList)),key=myList.__getitem__)
[0, 1, 2, 4, 3]
Les réponses avec enumerate
sont Nice, mais personnellement, je n'aime pas le lambda utilisé pour trier par valeur. Ce qui suit ne fait qu'inverser l'index et la valeur et le trie. Donc, il va d'abord trier par valeur, puis par index.
sorted((e,i) for i,e in enumerate(myList))
Mise à jour de la réponse avec enumerate
et itemgetter
:
sorted(enumerate(a), key=lambda x: x[1])
# [(0, 1), (1, 2), (2, 3), (4, 5), (3, 100)]
Compressez les listes ensemble: le premier élément du tuple sera l'index, le second est la valeur (puis triez-le en utilisant la deuxième valeur du tuple x[1]
, x est le tuple)
Ou en utilisant itemgetter
depuis le operator
module`:
from operator import itemgetter
sorted(enumerate(a), key=itemgetter(1))
Si vous ne voulez pas utiliser numpy,
sorted(range(len(seq)), key=seq.__getitem__)
est le plus rapide, comme démontré ici .
Les autres réponses sont fausses.
Lancer argsort
une fois n'est pas la solution. Par exemple, le code suivant:
import numpy as np
x = [3,1,2]
np.argsort(x)
donne array([1, 2, 0], dtype=int64)
qui n'est pas ce que nous voulons.
La réponse devrait être d'exécuter argsort
deux fois:
import numpy as np
x = [3,1,2]
np.argsort(np.argsort(x))
donne array([2, 0, 1], dtype=int64)
comme prévu.
J'ai effectué une rapide vérification de leurs performances avec perfplot (un projet de la mienne) et j'ai constaté qu'il était difficile de recommander autre chose que numpy (notez l'échelle du journal):
Code pour reproduire l'intrigue:
import perfplot
import numpy
def sorted_enumerate(seq):
return [i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))]
def sorted_enumerate_key(seq):
return [x for x, y in sorted(enumerate(seq), key=lambda x: x[1])]
def sorted_range(seq):
return sorted(range(len(seq)), key=seq.__getitem__)
def numpy_argsort(x):
return numpy.argsort(x)
perfplot.save(
"argsort.png",
setup=lambda n: numpy.random.Rand(n),
kernels=[sorted_enumerate, sorted_enumerate_key, sorted_range, numpy_argsort],
n_range=[2 ** k for k in range(15)],
xlabel="len(x)",
logx=True,
logy=True,
)
Vous devez essentiellement faire un argsort
. L’implémentation dont vous avez besoin dépend de l’utilisation des bibliothèques externes (par exemple, NumPy) ou du fait de rester pur-Python sans dépendances.
La question que vous devez vous poser est: voulez-vous le
Malheureusement, l'exemple de la question n'indique pas clairement ce qui est souhaité, car ils donneront le même résultat:
_>>> 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)
_
argsort
Si vous avez NumPy à votre disposition, vous pouvez simplement utiliser la fonction numpy.argsort
ou la méthode numpy.ndarray.argsort
.
Une implémentation sans NumPy a déjà été mentionnée dans d'autres réponses, je vais donc récapituler la solution la plus rapide selon la réponse de référence ici
_def argsort(l):
return sorted(range(len(l)), key=l.__getitem__)
_
Pour obtenir les index permettant de trier le tableau/la liste, vous pouvez simplement appeler argsort
sur le tableau ou la liste. J'utilise les versions NumPy ici mais l'implémentation Python devrait donner les mêmes résultats
_>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(arr)
array([1, 2, 0, 3], dtype=int64)
_
Le résultat contient les index nécessaires pour obtenir le tableau trié.
Puisque le tableau trié serait _[1, 2, 3, 4]
_, le tableau argsorted contient les index de ces éléments dans l'original.
1
_ et comme index _1
_ dans l'original, le premier élément du résultat est _1
_.2
_ est à l'index _2
_ dans l'original, donc le deuxième élément du résultat est _2
_.3
_ est à l'index _0
_ dans l'original et le troisième élément du résultat est donc _0
_.4
_ et étant à l'index _3
_ dans l'original, le dernier élément du résultat est _3
_.Dans ce cas, vous devrez appliquer argsort
deux fois :
_>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(np.argsort(arr))
array([2, 0, 1, 3], dtype=int64)
_
Dans ce cas :
3
_, qui est la troisième valeur la plus grande; son index _2
_ figurerait dans le tableau/la liste trié, de sorte que le premier élément est _2
_.1
_, qui est la plus petite valeur, de sorte qu'il aurait pour index _0
_ dans le tableau/la liste trié, de sorte que le deuxième élément est _0
_.2
_, qui est la deuxième valeur la plus petite. Il aurait donc index _1
_ dans le tableau/la liste triée de sorte que le troisième élément est _1
_.4
_ qui est la valeur la plus grande, de sorte qu'il aurait pour index _3
_ dans le tableau/la liste trié, de sorte que le dernier élément est _3
_.Importer numpy en tant que np
FOR INDEX
S=[11,2,44,55,66,0,10,3,33]
r=np.argsort(S)
[output]=array([5, 1, 7, 6, 0, 8, 2, 3, 4])
argsort Renvoie les index de S dans un ordre trié.
FOR VALUE
np.sort(S)
[output]=array([ 0, 2, 3, 10, 11, 33, 44, 55, 66])
Nous allons créer un autre tableau d’index de 0 à n-1, puis compresser ce fichier dans le tableau d’origine et le trier ensuite sur la base des valeurs originales.
ar = [1,2,3,4,5]
new_ar = list(Zip(ar,[i for i in range(len(ar))]))
new_ar.sort()
`