Fornire un proc ad un metodo come blocco
-
09-10-2019 - |
Domanda
dire Let Ho la seguente matrice:
arr = [[5, 1], [2, 7]]
e voglio trovare l'elemento minimo, confrontando il secondo elemento degli elementi. L'elemento minimo sarà [5, 1]
poiché 1
è inferiore 7
. Posso utilizzare il seguente codice:
arr.min {|a,b| a[1] <=> b[1]}
Per calcolare il massimo, posso fare lo stesso:
arr.max {|a,b| a[1] <=> b[1]}
Questo dà [2, 7]
.
Io uso lo stesso blocco di tutto il tempo. Mi piacerebbe avere quel blocco da qualche parte e fornire alla funzione min / max. Speravo qualcosa di simile:
blo = lambda {|a,b| a[1] <=> b[1]}
arr.min blo
avrebbe funzionato, ma non lo fece. Qualche idea su come posso fare questo?
Soluzione
Utilizzare l'operatore &
per trasformare un oggetto Proc
in un blocco.
arr.min &blo
Altri suggerimenti
@ di sepp2k risposta è quella più generale, ma nel tuo caso specifico, vorrei solo usare
arr.min_by(&:last)
arr.max_by(&:last)
poiché è molto più evidente di tutte quelle parentesi graffe e parentesi quadre e indici di array galleggiando.
Se tutto ciò che serve è minimo e massimo, si potrebbe utilizzare Enumerable#minmax
metodo e calcolare sia in una sola volta:
min, max = arr.minmax {|a,b| a[1] <=> b[1]}
#=> [[5, 1], [2, 7]]
min
#=> [5, 1]
max
#=> [2, 7]
Modifica: L'inferno, ho appena notato c'è anche minmax_by
, in modo da poter combinare con il metodo last
, e dispongono di:
min, max = arr.minmax_by &:last
come su questo?
=> [[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]]
Una soluzione più generale a problemi come questo per evitare matrici nidificate interamente ed usare una classe invece. È quindi possibile definire il <=> dell'operatore per quella classe, che vi dà accesso a tutte le funzioni del mixin comparabili (http://ruby-doc.org/core/classes/Comparable.html) ti dà il <, <= , ==,> = e> gli operatori e il metodo di 'mezzo?'
Questa è solo un esempio, nella vita reale si usa classi che descrivono ciò che immagazzinano:
class Duo
include Comparable
def initialize( a, b )
@a = a
@b = b
end
def <=>(rhs)
@b <=> rhs.b
end
end
Se si dispone di una serie di Duo oggetto è quindi possibile utilizzare le Min, Max, e funzioni di ordinamento senza dover definire l'operatore di confronto. Quindi ...
@a = Duo.new( 1, 10 )
@b = Duo.new( 2, 5 )
@c = Duo.new( 3, 1 )
[ @a, @b, @c ].sort
restituirebbe l'array [@c, @b, @a]
E
[@a, @b, @c].max
sarebbe tornato @a
Questo è molto di più il 'Rubino Way' di nidificato data-strutture con la logica che si basa su posizioni in array. Ci vuole un po 'più di lavoro all'inizio, ma lo troverete molto meglio nel lungo periodo.
Ruby è un oggetto molto orientato la programmazione lingua e fornisce strumenti molto potenti per l'uso. Raccomando la lettura di un libro come "The Ruby Programming Language" o "The Way Ruby" per avere una corretta visione d'insieme il potere della lingua.