In deinem Beispiel
a.sort
ist äquivalent zu
a.sort { |x, y| x <=> y }
Wie Sie wissen, um ein Array zu sortieren, müssen Sie in der Lage sein , seine Elemente zu vergleichen (wenn man das bezweifeln, versuchen Sie einfach , ohne jeden Vergleich jede Art Algorithmus zu implementieren, nicht <
, >
, <=
oder >=
).
Der von Ihnen bereitgestellte Block ist wirklich eine Funktion, die vom sort
Algorithmus aufgerufen wird , um zwei Elemente zu vergleichen. Das sind x
und y
bleiben einige Elemente des Eingabearrays, das der sort
Algorithmus während seiner Ausführung ausgewählt hat.
Der sort
Algorithmus geht davon aus, dass diese Vergleichsfunktion / dieser Vergleichsblock die Anforderungen für die Methode erfüllt <=>
:
- Rückgabe -1, wenn x <y
- 0 zurückgeben, wenn x = y
- Geben Sie 1 zurück, wenn x> y
Wenn keine angemessene Vergleichsfunktion / kein adäquater Vergleichsblock bereitgestellt wird, führt dies zu einem Array, dessen Reihenfolge undefiniert ist.
Sie sollten jetzt verstehen, warum
a.sort { |x, y| x <=> y }
und
a.sort { |x, y| y <=> x }
Geben Sie dasselbe Array in entgegengesetzter Reihenfolge zurück.
Wenn Sie die Vergleichsfunktion <=>
für eine Ihrer Klassen implementieren , erhalten Sie Folgendes, um zu erläutern, was Tate Johnson hinzugefügt hat
- Sie können das Modul enthalten
Comparable
in der Klasse , die für Sie die folgenden Methoden automatisch definieren: between?
, ==
, >=
, <
, <=
und >
.
- Instanzen Ihrer Klasse können jetzt mit dem Standardaufruf (dh ohne Argument) sortiert werden
sort
.
Beachten Sie, dass das <=>
Verfahren vorgesehen ist , bereits überall dort , wo es sinnvoll , in Rubys Standardbibliothek macht ( Bignum
, Array
, File::Stat
, Fixnum
, String
, Time
, etc ...).
<=>
eine Methode ist, die in definiertComparable
und gemischt wirdString
.Fixnum
undBignum
auch definieren<=>
. Sie können<=>
in jeder Klasse implementieren, in der Sortierung oder Vergleiche erforderlich sind.<=>
ist bekannt als der Raumschiff-BetreiberWenn Sie ein Array von beispielsweise zu sortierenden Ganzzahlen haben, ist es für die
sort
Methode ziemlich einfach , die Elemente richtig zu ordnen - kleinere Zahlen zuerst, größere am Ende. Das ist, wenn Sie gewöhnlichesort
, ohne Block verwenden.Wenn Sie jedoch andere Objekte sortieren, muss möglicherweise eine Möglichkeit bereitgestellt werden, (jeweils) zwei davon zu vergleichen. Angenommen, Sie haben eine Reihe von Klassenobjekten
Person
. Sie können wahrscheinlich nicht erkennen, ob das Objektbob
größer als das Objekt istmike
(dh in der KlassePerson
ist keine Methode<=>
implementiert). In diesem Fall müssen Sie Code bereitstellen, um zu erklären, in welcher Reihenfolge diese Objekte nachsort
Methode sortiert werden sollen. Hier setzt die Blockform an.people.sort{|p1,p2| p1.age <=> p2.age} people.sort{|p1,p2| p1.children.count <=> p2.children.count}
usw. In all diesen Fällen
sort
sortiert die Methode sie auf die gleiche Weise - es wird der gleiche Algorithmus verwendet. Was anders ist, ist die Vergleichslogik.quelle
people.sort{|p1,p2| p1.age <=> p2.age}
könnte umgeschrieben werden alspeople.sort_by{|p| p.age}
Die Antwort von @OscarRyz hat mir die Frage, wie die Sortierung funktioniert, sehr klar gemacht
{ |x, y| y <=> x }
Nach meinem Verständnis gebe ich hier an, wie der Zustand des Arrays nach jedem Vergleich für die obigen Blockergebnisse aussehen würde.
Hinweis: Die Referenz zum Drucken der Werte der Blockparameter e1, e2 wurde vom Ruby-Forum abgerufen
1.9.3dev :001 > a = %w(d e a w f k) 1.9.3dev :003 > a.sort { |e1, e2| p [e2, e1]; e2 <=> e1 } ["w", "d"] ["k", "w"] ["k", "d"] ["k", "e"] ["k", "f"] ["k", "a"] ["f", "a"] ["d", "f"] ["d", "a"] ["d", "e"] ["e", "f"] => ["w", "k", "f", "e", "d", "a"]
Ein erratener Array-Status zur Laufzeit nach jedem Vergleich:
[e2, e1] Comparsion Result Array State ["w", "d"] 1 ["w", "e", "a", "d", "f", "k"] ["k", "w"] -1 ["w", "e", "a", "d", "f", "k"] ["k", "d"] 1 ["w", "e", "a", "k", "f", "d"] ["k", "e"] 1 ["w", "k", "a", "e", "f", "d"] ["k", "f"] 1 ["w", "k", "a", "e", "f", "d"] ["k", "a"] 1 ["w", "k", "a", "e", "f", "d"] ["f", "a"] 1 ["w", "k", "f", "e", "a", "d"] ["d", "f"] -1 ["w", "k", "f", "e", "a", "d"] ["d", "a"] 1 ["w", "k", "f", "e", "d", "a"] ["d", "e"] -1 ["w", "k", "f", "e", "d", "a"] ["e", "f"] -1 ["w", "k", "f", "e", "d", "a"] (Result)
Vielen Dank,
Jignesh
quelle
<=>
ist eine Methode ist Ruby, die zurückgibt (self.<=>( argument )
)x
undy
sind Elemente des Arrays. Wenn kein Block bereitgestellt wird, verwendet diesort
Funktionx<=>y
, andernfalls sagt das Ergebnis des Blocks, ob x vor y stehen soll.array.sort{|x, y| some_very_complicated_method(x, y) }
Wenn some_very_complicated_method (x, y) smth zurückgibt, das <0 ist, wird x als <als y betrachtet und so weiter ...
quelle
Einige verschiedene Punkte:
x
undy
werden Blockparameter genannt. Die Sortiermethode sagt im Grunde: "Ich gebe Ihnen x und y, Sie bestimmen, ob x oder y zuerst kommen sollen, und ich kümmere mich um das langweilige Zeug in Bezug auf das Sortieren."<=>
wird als Raumschiffbetreiber bezeichnet .quelle
Im:
a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
x
undy
sind die Elemente, die vom Sortieralgorithmus verglichen werden.Dies ist nützlich, um für benutzerdefinierte Klassen zu definieren, welches Element vor dem anderen stehen soll.
Für Basisdaten (Zahlen, Zeichenfolgen, Datum usw.) ist die natürliche Reihenfolge vordefiniert, aber für Kundenelemente (dh Mitarbeiter) definieren Sie in einem Vergleich, wer vor wem geht. Dieser Block gibt Ihnen die Möglichkeit, dies zu definieren.
Dort vergleichen sie die Elemente in absteigender Reihenfolge (diejenigen mit "höherem" Wert werden zuerst verwendet) und nicht in der natürlichen Reihenfolge (
x<=>y
)Die
<=>
Methode steht für "compareTo" und gibt 0 zurück, wenn die Elemente äquivalent sind, oder<
0, wennx
vorher geht,y
oder>
0, wennx
geht nachhery
quelle
Ich glaube | x, y | y <=> x vergleicht zwei Elemente gleichzeitig in absteigender Reihenfolge, wie in: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-3C-3D- 3E Sagen Sie mit ["d", "a", "e", "c", "b"], "d" und "a" scheinen zuerst verglichen zu werden. Da es dann absteigend ist, bleiben beide in derselben Reihenfolge, da d weniger als a ergibt. Dann werden d und e ausgewertet. "e" wird in die Position von "d" verschoben. Ohne die interne Funktionsweise des c-Codes zu kennen, ist es nicht möglich zu wissen, wohin d verschoben wird, aber ich denke, dieser Prozess wird fortgesetzt, bis alle Elemente sortiert sind. Die c-Funktionen:
VALUE rb_ary_cmp(VALUE ary1, VALUE ary2) { long len; VALUE v; ary2 = rb_check_array_type(ary2); if (NIL_P(ary2)) return Qnil; if (ary1 == ary2) return INT2FIX(0); v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2); if (v != Qundef) return v; len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2); if (len == 0) return INT2FIX(0); if (len > 0) return INT2FIX(1); return INT2FIX(-1); }
quelle