J'ai un tableau de hachages:
[
{ :foo => 'foo', :bar => 2 },
{ :foo => 'foo', :bar => 3 },
{ :foo => 'foo', :bar => 5 },
]
J'essaie de trier ce tableau par ordre décroissant en fonction de la valeur de :bar
dans chaque hachage.
J'utilise sort_by
pour trier le tableau ci-dessus:
a.sort_by { |h| h[:bar] }
Cependant, cela trie le tableau par ordre croissant. Comment puis-je le trier par ordre décroissant?
Une solution consistait à faire ce qui suit:
a.sort_by { |h| -h[:bar] }
Mais ce signe négatif ne semble pas approprié.
sort_by.reverse
est considérablement plus efficace que la réponse actuellement acceptée. Je crois que cela répond aussi mieux à la préoccupation que vous avez mentionnée ci-dessus pour «transmettre l'intention du code». En plus de cela, le Tin Man a mis à jour sa réponse pour la version actuelle de rubis. Cette question a été vue plus de 15k fois. Si vous pouvez gagner même 1 seconde du temps de chaque spectateur, je pense que ça vaut le coup.Réponses:
Il est toujours instructif de faire un point de repère sur les différentes réponses suggérées. Voici ce que j'ai découvert:
Je pense que c'est intéressant que @ Pablo
sort_by{...}.reverse!
soit le plus rapide. Avant d'exécuter le test, je pensais que ce serait plus lent que "-a[:bar]
" mais annuler la valeur s'avère plus long que pour inverser l'ensemble du tableau en une seule passe. Ce n'est pas vraiment une différence, mais chaque petite accélération aide.Voici les résultats pour Ruby 1.9.3p194 (2012-04-20 révision 35410) [x86_64-darwin10.8.0]:
Ce sont sur un vieux MacBook Pro. Les machines plus récentes ou plus rapides auront des valeurs plus faibles, mais les différences relatives resteront.
Voici une version un peu mise à jour sur du matériel plus récent et la version 2.1.1 de Ruby:
Nouveaux résultats exécutant le code ci-dessus en utilisant Ruby 2.2.1 sur un Macbook Pro plus récent. Encore une fois, les chiffres exacts ne sont pas importants, ce sont leurs relations:
Mis à jour pour Ruby 2.7.1 sur un MacBook Pro mi-2015:
La source de
Array#reverse
est:do *p2-- = *p1++; while (--len > 0);
copie les pointeurs vers les éléments dans l'ordre inverse si je me souviens bien de mon C, donc le tableau est inversé.la source
Juste une chose rapide, qui dénote l'intention de l'ordre décroissant.
(Pensera à une meilleure façon dans l'intervalle);)
la source
Vous pourriez faire:
la source
sort_by
était qu'il évitait d'exécuter la fonction de comparaison tant de foissort_by
est tellement plus efficace et plus lisible. Nier la valeur ou faire un revers à la fin sera plus rapide et plus lisible.* -1
elle ne fonctionne pas avec toutes les valeurs (par exemple, l'heure) etreverse
réorganisera les valeurs triées comme égalesJe vois que nous avons (à côté des autres) essentiellement deux options:
et
Bien que les deux méthodes vous donnent le même résultat lorsque votre clé de tri est unique, gardez à l'esprit que la
reverse
méthode inversera l'ordre des clés qui sont égales .Exemple:
Bien que vous n'ayez souvent pas besoin de vous en soucier, vous le faites parfois. Pour éviter un tel comportement, vous pouvez introduire une deuxième clé de tri (qui doit à coup sûr être unique au moins pour tous les éléments qui ont la même clé de tri):
la source
reverse
est différente. Je crois que cela gâchera également un type précédent, dans le cas où l'on essaie d'appliquer plusieurs types dans un certain ordre.Qu'en est-il de:
Ça marche!!
la source
sort
fonctionne, il est seulement plus rapide lors du tri des valeurs immédiates. Si vous devez creuser pour eux,sort_by
c'est plus rapide. Voir le benchmark.En ce qui concerne la suite de référence mentionnée, ces résultats valent également pour les tableaux triés.
sort_by
/reverse
c'est:Et les résultats:
la source
La solution simple de l'ascendant au descendant et vice versa est:
STRINGS
CHIFFRES
la source
Pour ceux qui aiment mesurer la vitesse en IPS;)
Et les résultats:
la source