J'ai une liste numérique:
myList = [1, 2, 3, 100, 5]
Maintenant, si je trie cette liste pour l'obtenir [1, 2, 3, 5, 100]
. Ce que je veux, ce sont les indices des éléments de la liste d'origine dans l'ordre trié, c'est-à-dire [0, 1, 2, 4, 3]
--- la fonction de tri de MATLAB qui renvoie à la fois les valeurs et les indices.
Réponses:
Si vous utilisez numpy, vous disposez de la fonction argsort ():
http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
Cela renvoie les arguments qui trieraient le tableau ou la liste.
la source
Quelque chose comme la prochaine:
enumerate(myList)
vous donne une liste contenant des tuples de (index, valeur):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 lalambda
raison d'être. Enfin, l'index d'origine de chaque élément trié est extrait à l'aide de la[i[0] for i in ...]
compréhension de la liste.la source
itemgetter(1)
place de la fonction lambdaitemgetter
fonction duoperator
module, FYI. Il fautfrom operator import itemgetter
donc l'utiliser.sorted_items, sorted_inds = zip(*sorted([(i,e) for i,e in enumerate(my_list)], key=itemgetter(1)))
x = [3,1,2]; numpy.argsort(x)
donne [1,2,0].la source
Les réponses
enumerate
sont agréables, mais personnellement, je n'aime pas le lambda utilisé pour trier par valeur. Ce qui suit inverse simplement l'index et la valeur et trie cela. Il va donc d'abord trier par valeur, puis par index.la source
Réponse mise à jour avec
enumerate
etitemgetter
: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 leoperator
module`:la source
J'ai fait une vérification rapide des performances avec perfplot (un de mes projets) et j'ai trouvé qu'il était difficile de recommander autre chose que numpy (notez l'échelle logarithmique):
Code pour reproduire l'intrigue:
la source
Si vous ne souhaitez pas utiliser numpy,
est le plus rapide, comme démontré ici .
la source
Essentiellement, vous devez faire une
argsort
, quelle implémentation dont vous avez besoin dépend si vous voulez utiliser des bibliothèques externes (par exemple NumPy) ou si vous voulez rester pure-Python sans dépendances.La question que vous devez vous poser est la suivante: voulez-vous
Malheureusement, l'exemple de la question ne précise pas ce qui est souhaité car les deux donneront le même résultat:
Choisir le
argsort
implémentationSi vous avez NumPy à votre disposition, vous pouvez simplement utiliser la fonction
numpy.argsort
ou la méthodenumpy.ndarray.argsort
.Une implémentation sans NumPy a déjà été mentionnée dans certaines autres réponses, je vais donc récapituler la solution la plus rapide en fonction de la réponse de référence ici
Obtenir les indices qui trieraient le tableau / la liste
Pour obtenir les indices qui trieraient le tableau / la liste, vous pouvez simplement appeler
argsort
le tableau ou la liste. J'utilise les versions de NumPy ici mais l'implémentation Python devrait donner les mêmes résultatsLe résultat contient les indices nécessaires pour obtenir le tableau trié.
Puisque le tableau trié serait
[1, 2, 3, 4]
le tableau argsorted contient les indices de ces éléments dans l'original.1
et elle est à l'index1
dans l'original, donc le premier élément du résultat est1
.2
est à l'index2
dans l'original donc le deuxième élément du résultat est2
.3
est à l'index0
dans l'original, donc le troisième élément du résultat est0
.4
et elle est à l'index3
dans l'original, donc le dernier élément du résultat est3
.Obtention des indices que les éléments auraient dans le tableau / liste trié
Dans ce cas, vous devrez postuler
argsort
deux fois :Dans ce cas :
3
, qui est la troisième plus grande valeur de sorte qu'il aurait un index2
dans le tableau / liste trié de sorte que le premier élément est2
.1
, qui est la plus petite valeur pour qu'il ait un index0
dans le tableau / liste trié, de sorte que le deuxième élément l'est0
.2
, qui est la deuxième plus petite valeur, de sorte qu'il aurait un index1
dans le tableau / liste trié, de sorte que le troisième élément l'est1
.4
la valeur la plus élevée, il aurait donc un index3
dans le tableau / la liste trié, de sorte que le dernier élément l'est3
.la source
Les autres réponses sont FAUX.
Courir
argsort
une fois n'est pas la solution. Par exemple, le code suivant:des rendements
array([1, 2, 0], dtype=int64)
qui ne sont pas ce que nous voulons.La réponse devrait être d'exécuter
argsort
deux fois:donne
array([2, 0, 1], dtype=int64)
comme prévu.la source
x[2]
(3) l'élément le plus petit etx[1]
(1) l'élément le plus grand (puisque le tri des entiers les ordonne de la plus petite valeur à la plus grande valeur). En outre, avec l'exemple des OP, un seulnp.argsort([1, 2, 3, 100, 5])
rendementarray([0, 1, 2, 4, 3])
, qui semble être les indices souhaités par l'OP.arr = [1,2,3,100, 5, 9] res = np.argsort(arr) print(res)
nous obtenons[0 1 2 4 5 3]
ce qui est faux.arr[res]
rendementsarray([ 1, 2, 3, 5, 9, 100])
, ce qui semble être parfaitement bien, car ce tableau résultant est dans l'ordre (croissant).arr=[1,2,3,100, 5, 9]
, je m'attends à ce que la sortie soitinds=[0,1,2,5,3,4]
, parce que c'est l'ordre dans lequel vous ordonnerez les éléments (de plus en plus) - 1 est à la place des 0, 2 à la 1ère place, ...., 5 sur la 3e place et 9 à la 4e place. Afin d'obtenir cette sortie (inds
), je dois exécuterargsort
deux fois, comme je l'ai mentionné.sort
, je pense que l'OP veut l'autre fonctionnalité, tout commenp.argsort
est normalement utilisée (où l'on peut utiliserarr[np.argsort[arr]]
pour obtenir le tableau trié, comme dans le dernier exemple MATLAB). Votre réponse s'applique plutôt à ce cas / question .Importer numpy comme np
POUR INDEX
argsort Renvoie les indices de S dans l'ordre trié
POUR LA VALEUR
la source
Nous allons créer un autre tableau d'index de 0 à n-1 Puis compresser ceci dans le tableau d'origine, puis le trier sur la base des valeurs d'origine
"
la source