2010-11-24 23 views
56

Mon hachage d'entrée: h = { "a" => 20, "b" => 30, "c" => 10 }par ordre décroissant par la valeur d'un Hash dans Ruby

tri croissant: h.sort {|a,b| a[1]<=>b[1]} #=> [["c", 10], ["a", 20], ["b", 30]]

Mais, je dois [["b", 30], ["a", 20], ["c", 10]]

Comment est peut-on faire fonctionner l'inverse, que signifie <=>?

Répondre

151

Vous pouvez l'avoir plus propre, plus clair et plus rapide, tout à la fois! Comme ceci:

h.sort_by {|k,v| v}.reverse 

I benchmarkée timings sur 3000 itérations de tri un hachage 1000 éléments avec des valeurs aléatoires, et a obtenu ces temps:

h.sort {|x,y| -(x[1]<=>y[1])} -- 16.7s 
h.sort {|x,y| y[1] <=> x[1]} -- 12.3s 
h.sort_by {|k,v| -v} -- 5.9s 
h.sort_by {|k,v| v}.reverse -- 3.7 
+2

Visuellement, c'est plus propre mais cela provoque une traversée supplémentaire de la collection pour l'inverser. –

+14

Et vous pourriez penser que ce serait mauvais! Mais voir les horaires que j'ai ajoutés ci-dessus ... –

+0

@ glennmcdonald pouvez-vous s'il vous plaît me dire comment peut-on calculer les horaires de chaque appel à ruby? – boddhisattva

8

<=> compare les deux opérandes, en renvoyant -1 si le premier est inférieur, 0 s'ils sont égaux et 1 si le premier est supérieur. Cela signifie que vous pouvez simplement faire -(a[1]<=>b[1]) pour annuler la commande.

+1

Je préfère toujours voir il a écrit avec les éléments "a" et "b" échangés, plutôt que de nier le résultat. Avec eux échangé je dois seulement regarder leur commande pour voir qu'ils sont en arrière pour savoir que c'est inversé. Lorsque la valeur de «<=>» est annulée, je dois encore regarder la comparaison pour savoir ce qui se passe. C'est un point mineur mais quelque chose dont je suis conscient parce que je peux sentir que mon cerveau doit faire la deuxième vérification après avoir fait un "Quoi!" –

+1

@Greg: Je vois vraiment pourquoi vous préférez l'inverse. Je suis le contraire: Pour mes yeux de balayage, 'b [1] <=> a [1]' ressemble à 'a [1] <=> b [1]' et je ressens le besoin de m'arrêter et de vérifier, alors que la négation fait il est immédiatement évident que nous faisons une sorte inverse. – Chuck

+0

Je comprends votre point de vue aussi. L'une ou l'autre façon de procéder exige encore un examen attentif des valeurs comparées. Peut-être avons-nous besoin d'un opérateur différent - '> = <' pour l'ordre inverse? Nah, ce serait tout aussi mauvais. C'est la construction entière, mais je préfère '<=>' sur une approche plus verbeuse où nous devrions appeler certains noms de méthodes. –

10
h.sort {|a,b| b[1]<=>a[1]} 
+6

J'ai downvoted ce commentaire, pas parce que la réponse est fausse, mais parce que vous n'expliquez pas pourquoi c'est la bonne réponse. Le questionneur a même demandé spécifiquement ce que signifie "<=>" - ainsi (s) il est clairement après une explication de la façon dont tout cela fonctionne. C'est une bonne idée pour aider de cette façon :) –

+0

PS: voir la politique de révision Stack Overflow sur meta pour en savoir plus: http://meta.stackexchange.com/questions/74194/how-to-review-can-we-agree -on-a-review-policy –

5

Super simple: h.sort_by { |k, v| -v }