Disons que j'ai deux listes:
list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']
Si je cours list1.sort()
, il le triera, [1,1,2,3,4]
mais y a-t-il un moyen de se list2
synchroniser également (pour que je puisse dire que l'élément 4
appartient à 'three'
)? Ainsi, le résultat attendu serait:
list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']
Mon problème est que j'ai un programme assez complexe qui fonctionne bien avec les listes, mais j'ai en quelque sorte besoin de commencer à référencer certaines données. Je sais que c'est une situation parfaite pour les dictionnaires, mais j'essaie d'éviter les dictionnaires dans mon traitement car j'ai besoin de trier les valeurs clés (si je dois utiliser des dictionnaires, je sais comment les utiliser).
Fondamentalement, la nature de ce programme est que les données sont présentées dans un ordre aléatoire (comme ci-dessus), je dois les trier, les traiter puis envoyer les résultats (l'ordre n'a pas d'importance mais les utilisateurs doivent savoir quel résultat appartient à quel clé). J'ai pensé à le mettre d'abord dans un dictionnaire, puis à trier la liste un mais je n'aurais aucun moyen de différencier les éléments dans le avec la même valeur si l'ordre n'est pas maintenu (cela peut avoir un impact lors de la communication des résultats aux utilisateurs). Donc, idéalement, une fois que j'aurais les listes, je préfère trouver un moyen de trier les deux listes ensemble. Est-ce possible?
Réponses:
Une approche classique de ce problème consiste à utiliser l'idiome "décorer, trier, décorer", qui est particulièrement simple en utilisant la fonction intégrée de python
zip
:Ce ne sont bien sûr plus des listes, mais c'est facilement résolu, si cela compte:
Il convient de noter que ce qui précède peut sacrifier la vitesse au profit de la concision; la version en place, qui prend 3 lignes, est un peu plus rapide sur ma machine pour les petites listes:
En revanche, pour les listes plus volumineuses, la version une ligne pourrait être plus rapide:
Comme le souligne Quantum7, la suggestion de JSF est encore un peu plus rapide, mais ce ne sera probablement qu'un peu plus rapide, car Python utilise le même idiome DSU en interne pour tous les types basés sur des clés. Cela se passe juste un peu plus près du métal nu. (Cela montre à quel point les
zip
routines sont optimisées !)Je pense que l'
zip
approche basée sur la base est plus flexible et un peu plus lisible, donc je la préfère.la source
*
opérateur effectue le déballage des arguments ,zip(*x)
a la propriété intéressante qu'il est son propre inverse:l = [(1, 2), (3, 4)]; list(zip(*zip(*l))) == l
retourneTrue
. C'est effectivement un opérateur de transposition.zip()
seul est le même opérateur, mais suppose que vous avez décompressé la séquence d'entrée manuellement.Vous pouvez trier les index en utilisant des valeurs comme clés:
Pour obtenir des listes triées avec des index triés:
Dans votre cas, vous ne devriez pas avoir
list1
,list2
mais plutôt une seule liste de paires:C'est facile à créer; il est facile de trier en Python:
Trier uniquement par la première valeur:
la source
list()
déplacermap()
si vous souhaitez utiliser ce code en Python 3.sorted_list1 = list(map(list1.__getitem__, indexes))
un pourrait fairesorted_list1 = [list1[i] for i in indexes]
.J'ai utilisé la réponse donnée par senderle pendant longtemps jusqu'à ce que je découvre
np.argsort
. Voici comment cela fonctionne.Je trouve cette solution plus intuitive et ça marche vraiment bien. La performance:
Même si ce
np.argsort
n'est pas le plus rapide, je le trouve plus facile à utiliser.la source
TypeError: only integer arrays with one element can be converted to an index
J'obtiens une erreur lors de l'exécution de votre exemple: (Python 2.7.6, numpy 1.8.2). Pour résoudre ce problème, list1 et list2 doivent être déclarés comme des tableaux numpy.np.argsort
ne pas essayer de se convertir ennp.array
interne.Transformée schwartzienne . Le tri Python intégré est stable, donc les deux
1
s ne posent pas de problème.la source
Qu'en est-il de:
la source
Vous pouvez utiliser les fonctions
zip()
etsort()
pour ce faire:J'espère que cela t'aides
la source
Vous pouvez utiliser l'argument clé dans la méthode sorted () sauf si vous avez deux mêmes valeurs dans list2.
Le code est donné ci-dessous:
Il trie list2 en fonction des valeurs correspondantes dans list1, mais assurez-vous que lors de son utilisation, deux valeurs de list2 ne sont pas évaluées égales car la fonction list.index () donne la première valeur
la source
Une façon est de suivre où chaque index va en triant l'identité [0,1,2, .. n]
Cela fonctionne pour n'importe quel nombre de listes.
Déplacez ensuite chaque élément à sa position. Il est préférable d'utiliser des épissures.
Notez que nous aurions pu itérer les listes sans même les trier:
la source
Si vous utilisez numpy, vous pouvez utiliser
np.argsort
pour obtenir les indices triés et appliquer ces indices à la liste. Cela fonctionne pour n'importe quel nombre de listes que vous souhaitez trier.la source
une solution algorithmique:
Sorties:
->
Vitesse de sortie:0.2s
la source
Une autre approche pour conserver l'ordre d'une liste de chaînes lors du tri par rapport à une autre liste est la suivante:
production
la source
Je voudrais développer la réponse d' Open jfs , qui a très bien fonctionné pour mon problème: trier deux listes par une troisième liste décorée :
Nous pouvons créer notre liste décorée de n'importe quelle manière, mais dans ce cas, nous la créerons à partir des éléments de l'une des deux listes originales que nous voulons trier:
Nous pouvons maintenant appliquer la solution de jfs pour trier nos deux listes par la troisième
Edit: Hé les gars, j'ai fait un article de blocage à ce sujet, vérifiez-le si vous en avez envie :) 🐍🐍🐍
la source
la source