Ich habe eine Reihe von Hashes:
[
{ :foo => 'foo', :bar => 2 },
{ :foo => 'foo', :bar => 3 },
{ :foo => 'foo', :bar => 5 },
]
Ich versuche, dieses Array in absteigender Reihenfolge nach dem Wert von :bar
in jedem Hash zu sortieren .
Ich benutze sort_by
, um über Array zu sortieren:
a.sort_by { |h| h[:bar] }
Dadurch wird das Array jedoch in aufsteigender Reihenfolge sortiert. Wie sortiere ich es in absteigender Reihenfolge?
Eine Lösung bestand darin, Folgendes zu tun:
a.sort_by { |h| -h[:bar] }
Dieses negative Vorzeichen erscheint jedoch nicht angemessen.
sort_by.reverse
dramatisch effizienter ist als die derzeit akzeptierte Antwort. Ich glaube, es geht auch besser auf das oben erwähnte Problem ein, "die Absicht des Codes zu vermitteln". Darüber hinaus hat der Blechmann seine Antwort für die aktuelle Version von Ruby aktualisiert. Diese Frage wurde über 15.000 Mal angezeigt. Wenn Sie sogar 1 Sekunde der Zeit jedes Zuschauers sparen können, denke ich, dass es sich lohnt.Antworten:
Es ist immer aufschlussreich, einen Benchmark für die verschiedenen vorgeschlagenen Antworten durchzuführen. Folgendes habe ich herausgefunden:
Ich finde es interessant, dass @ Pablo's
sort_by{...}.reverse!
am schnellsten ist. Vor dem Ausführen des Tests dachte ich, es wäre langsamer als "-a[:bar]
", aber das Negieren des Werts dauert länger als das Umkehren des gesamten Arrays in einem Durchgang. Es ist kein großer Unterschied, aber jede kleine Beschleunigung hilft.Hier sind die Ergebnisse für Ruby 1.9.3p194 (2012-04-20 Revision 35410) [x86_64-darwin10.8.0]:
Diese befinden sich auf einem alten MacBook Pro. Neuere oder schnellere Maschinen haben niedrigere Werte, aber die relativen Unterschiede bleiben bestehen.
Hier ist eine etwas aktualisierte Version auf neuerer Hardware und der 2.1.1-Version von Ruby:
Neue Ergebnisse beim Ausführen des obigen Codes mit Ruby 2.2.1 auf einem neueren Macbook Pro. Auch hier sind die genauen Zahlen nicht wichtig, es sind ihre Beziehungen:
Aktualisiert für Ruby 2.7.1 auf einem MacBook Pro Mitte 2015:
Die Quelle für
Array#reverse
ist:do *p2-- = *p1++; while (--len > 0);
kopiert die Zeiger in umgekehrter Reihenfolge auf die Elemente, wenn ich mich richtig an mein C erinnere, sodass das Array umgekehrt ist.quelle
Nur eine kurze Sache, die die Absicht der absteigenden Reihenfolge anzeigt.
(Werde mir in der Zwischenzeit einen besseren Weg überlegen);)
quelle
Du könntest es tun:
quelle
sort_by
sort_by
ist so viel effizienter und lesbarer. Das Negieren des Werts oder das Umkehren am Ende ist schneller und besser lesbar.* -1
sie nicht mit allen Werten (z. B. Zeit) funktioniert undreverse
Werte neu sortiert, die gleich sortiert sindIch sehe, dass wir (neben anderen) grundsätzlich zwei Möglichkeiten haben:
und
Während beide Möglichkeiten , wie Sie das gleiche Ergebnis , wenn der Sortierschlüssel eindeutig zuzuordnen sind, bedenken Sie, dass die
reverse
Art und Weise wird die Reihenfolge der Tasten umkehren , die gleich sind .Beispiel:
Während Sie sich oft nicht darum kümmern müssen, tun Sie dies manchmal. Um ein solches Verhalten zu vermeiden, können Sie einen zweiten Sortierschlüssel einführen (der zumindest für alle Elemente mit demselben Sortierschlüssel eindeutig sein muss):
quelle
reverse
unterschiedlich ist. Ich glaube, es wird auch eine vorherige Sortierung durcheinander bringen, falls versucht wird, mehrere Sortierungen in einer bestimmten Reihenfolge anzuwenden.Wie wäre es mit:
Es klappt!!
quelle
sort
es funktioniert, ist es nur schneller, wenn unmittelbare Werte sortiert werden. Wenn Sie nach ihnen graben müssen,sort_by
ist das schneller. Siehe den Benchmark.In Bezug auf die erwähnte Benchmark-Suite gelten diese Ergebnisse auch für sortierte Arrays.
sort_by
/reverse
es ist:Und die Ergebnisse:
quelle
Einfache Lösung von aufsteigend nach absteigend und umgekehrt ist:
STRINGS
Ziffern
quelle
Für diejenigen, die Geschwindigkeit in IPS messen möchten;)
Und Ergebnisse:
quelle