Proporcionar un proc a un método como un bloque
-
09-10-2019 - |
Pregunta
Vamos a decir que tengo la siguiente matriz:
arr = [[5, 1], [2, 7]]
y yo quiero encontrar el elemento mínimo, comparando el segundo elemento de los elementos. El elemento mínima será [5, 1]
desde 1
es menor que 7
. Puedo usar el siguiente código:
arr.min {|a,b| a[1] <=> b[1]}
Para el cálculo de la máxima, que puede hacer lo mismo:
arr.max {|a,b| a[1] <=> b[1]}
Esto da [2, 7]
.
Yo uso el mismo bloque todo el tiempo. Me gustaría tener ese bloque en algún lugar y proporcionarla a la función de mínimo / máximo. Yo esperaba algo como:
blo = lambda {|a,b| a[1] <=> b[1]}
arr.min blo
funcionaría, pero no fue así. Alguna idea sobre cómo puedo hacer esto?
Solución
Use el operador &
para girar un objeto Proc
en un bloque.
arr.min &blo
Otros consejos
@ de sepp2k es el más general, pero en su caso concreto, me gustaría simplemente utilizar
arr.min_by(&:last)
arr.max_by(&:last)
ya que es más más evidente que todos esos llaves y corchetes y los índices de matriz flotando alrededor.
Si todo lo que necesita es mínima y máxima, podría utilizar Enumerable#minmax
método y calcular tanto a la vez:
min, max = arr.minmax {|a,b| a[1] <=> b[1]}
#=> [[5, 1], [2, 7]]
min
#=> [5, 1]
max
#=> [2, 7]
Editar: Hell, sólo se dio cuenta de que también es minmax_by
, por lo que se puede combinar con el método last
, y tienen:
min, max = arr.minmax_by &:last
¿qué tal esto?
=> [[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 solución más general a problemas como esto es para evitar matrices anidadas por completo y utilizar una clase en su lugar. A continuación, puede definir el <=> operador para esa clase, que le da acceso a todas las funciones en el mixin Comparable (http://ruby-doc.org/core/classes/Comparable.html) le da la <, <= , ==,> =, y> operadores y el método 'entre?'
Esto es sólo un ejemplo, en la vida real que usaría clases que describen lo que la tienda:
class Duo
include Comparable
def initialize( a, b )
@a = a
@b = b
end
def <=>(rhs)
@b <=> rhs.b
end
end
Si usted tiene una serie de Duo oponerse a continuación, puede utilizar los minutos, y funciones de clasificación máximo sin tener que definir el operador de comparación. Así que ...
@a = Duo.new( 1, 10 )
@b = Duo.new( 2, 5 )
@c = Duo.new( 3, 1 )
[ @a, @b, @c ].sort
devolvería el array [@c, @b, @a]
y
[@a, @b, @c].max
volvería @a
Esto es mucho más la 'Rubí Way' de anidada estructuras de datos con la lógica que se basa en las posiciones en las matrices. Se tarda un poco más de trabajo al principio, pero lo encontrará más mejor en el largo plazo.
Ruby es un lenguaje de programación orientado a objetos y proporciona herramientas muy poderosas para su uso. Lo recomiendo la lectura de un libro como "The Ruby Lenguaje de programación" o "The Ruby Way" para obtener una visión adecuada de la potencia del lenguaje.