Stellt eine proc ein Verfahren als Block
-
09-10-2019 - |
Frage
Lassen Sie uns sagen, ich habe die folgende Array:
arr = [[5, 1], [2, 7]]
und ich möchte das kleinste Element finden, das zweite Element der Elemente zu vergleichen. Das kleinste Element wird [5, 1]
da 1
weniger als 7
. Ich kann den folgenden Code verwenden:
arr.min {|a,b| a[1] <=> b[1]}
Für die maximale Berechnung kann ich das gleiche tun:
arr.max {|a,b| a[1] <=> b[1]}
Das gibt [2, 7]
.
Ich verwende den gleichen Block die ganze Zeit. Ich möchte diesen Block irgendwo haben und liefern sie an die Min- / Max-Funktion. Ich hoffte, dass so etwas wie:
blo = lambda {|a,b| a[1] <=> b[1]}
arr.min blo
funktionieren würde, aber es kam nicht. Jede Idee, wie kann ich das tun?
Lösung
Mit dem &
Bediener ein Proc
Objekt in einen Block zu drehen.
arr.min &blo
Andere Tipps
@ sepp2k Antwort ist das allgemeinere, aber in Ihrem speziellen Fall würde ich nur verwenden
arr.min_by(&:last)
arr.max_by(&:last)
denn das ist viel offensichtlicher als all diese geschweiften Klammern und eckige Klammern gesetzt und Array-Indizes im Umlauf.
Wenn alles, was Sie brauchen, Minimum und Maximum, können Sie Enumerable#minmax
Methode verwenden und beide berechnen auf einmal:
min, max = arr.minmax {|a,b| a[1] <=> b[1]}
#=> [[5, 1], [2, 7]]
min
#=> [5, 1]
max
#=> [2, 7]
Edit: Verdammt, ich habe gerade bemerkt, gibt es auch minmax_by
, so dass Sie es mit last
Verfahren kombinieren und haben:
min, max = arr.minmax_by &:last
Wie wäre das?
=> [[5, 4], [9, 5], [2, 7]]
>> arr.sort!{|x,y| x[1]<=>y[1] }
=> [[5, 4], [9, 5], [2, 7]]
>> min,max=arr[0],arr[-1]
=> [[5, 4], [2, 7]]
Eine allgemeine Lösung für Probleme wie diese ist verschachtelte Arrays ganz zu vermeiden und eine Klasse stattdessen verwenden. Sie können den Operator <=> für diese Klasse dann definieren Ihnen den Zugriff auf alle Funktionen, die in dem Vergleich mixin geben (http://ruby-doc.org/core/classes/Comparable.html) gibt Ihnen die <, <= , ==,> = und> Betreiber und die Methode 'zwischen?'
Dies ist nur ein Beispiel, im wirklichen Leben würden Sie Klassen verwenden, die beschreiben, was sie speichern:
class Duo
include Comparable
def initialize( a, b )
@a = a
@b = b
end
def <=>(rhs)
@b <=> rhs.b
end
end
Wenn Sie ein Array von Duo haben Objekt, das Sie dann die Minimal-, Maximal- verwenden können und Sortierfunktionen, ohne den Vergleichsoperator definieren zu müssen. So ...
@a = Duo.new( 1, 10 )
@b = Duo.new( 2, 5 )
@c = Duo.new( 3, 1 )
[ @a, @b, @c ].sort
würde das Array zurück [@c, @b, @a]
Und
[@a, @b, @c].max
zurückkehren würde @a
Das ist viel mehr der ‚Ruby Way‘ als verschachtelte Datenstrukturen mit Logik, die in Arrays auf Positionen beruht. Es dauert etwas mehr Arbeit am Anfang, aber Sie werden es viel besser auf lange Sicht finden.
Ruby ein sehr Objekt Programmiersprache orientiert und bietet eine sehr leistungsfähige Werkzeuge für Sie zu nutzen. Ich empfehle durchaus ein Buch wie „Die Programmiersprache Ruby“ oder „The Ruby Way“ lese einen richtigen Überblick über die Macht der Sprache zu erhalten.