web-dev-qa-db-fra.com

Comment obtenir les index d'un tableau trié dans Python

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.

170
Gyan

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.

159
Matthew Lewis

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 ...].

124
Roman Bodnarchuk
myList = [1, 2, 3, 100, 5]    
sorted(range(len(myList)),key=myList.__getitem__)

[0, 1, 2, 4, 3]
66
robert king

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))
19
Ant6n

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 operatormodule`:

from operator import itemgetter
sorted(enumerate(a), key=itemgetter(1))
11
Matt

Si vous ne voulez pas utiliser numpy,

sorted(range(len(seq)), key=seq.__getitem__)

est le plus rapide, comme démontré ici .

4
mab

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.

2
shahar_m

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):

enter image description here


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,
)
2
Nico Schlömer

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

  • des index qui trieraient le tableau/la liste
  • les indices que les éléments auraient dans le tableau/la liste triée

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)
_

Choix de l'implémentation 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__)
_

Obtenir les index qui trieraient le tableau/la liste

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.

  • La plus petite valeur est _1_ et comme index _1_ dans l'original, le premier élément du résultat est _1_.
  • Le _2_ est à l'index _2_ dans l'original, donc le deuxième élément du résultat est _2_.
  • Le _3_ est à l'index _0_ dans l'original et le troisième élément du résultat est donc _0_.
  • La plus grande valeur _4_ et étant à l'index _3_ dans l'original, le dernier élément du résultat est _3_.

Obtenir les index que les éléments auraient dans le tableau/la liste triée

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 :

  • le premier élément de l'original est _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_.
  • le deuxième élément de l'original est _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_.
  • le troisième élément de l'original est _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_.
  • le quatrième élément de l'original est _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_.
1
MSeifert

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])
0
Aditya kumar

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()

`

0
Jai dewani