Cómo encontrar un mínimo / máximo con Ruby

415

Quiero usar min(5,10), o Math.max(4,7). ¿Hay funciones a este efecto en Ruby?

obuzek
fuente

Respuestas:

723

Tu puedes hacer

[5, 10].min

o

[4, 7].max

Vienen del módulo Enumerable , por lo que todo lo que incluya Enumerabletendrá esos métodos disponibles.

v2.4 presenta los propios Array#miny Array#max, que son mucho más rápidos que los métodos de Enumerable porque omiten las llamadas #each.

@nicholasklick menciona otra opción, Enumerable#minmaxpero esta vez devolviendo una serie de [min, max].

[4, 5, 7, 10].minmax
=> [4, 10]
theIV
fuente
3
@kaz No estoy seguro de entender tu comentario.
Ziggy
3
@Kaz ... ¿te das cuenta de que std::max(4, 7)tiene más "puntuación" que [4, 7].max?
tckmn
3
@Doorknob Te das cuenta de que std::maxse puede importar a tu espacio de nombres, por lo que simplemente se convierte max(4, 7). Espere; mirando arriba, veo que ya dije eso.
Kaz
18
La puntuación no es el problema aquí. Una asignación completa del montón para obtener el máximo de algunos valores es la fealdad subyacente aquí.
kdbanman
77
Ruby es principalmente para el programador, no para la computadora. En palabras de Matz, "espero ver a Ruby ayudar a todos los programadores del mundo a ser productivos, disfrutar de la programación y ser felices. Ese es el propósito principal del lenguaje Ruby". Eso es de la página de Wikipedia en Ruby.
codificación aaron el
52

Puedes usar

[5,10].min 

o

[4,7].max

Es un método para matrices.

Diego Dias
fuente
20
Técnicamente es un método para Enumerables, no Arrays.
Meagar
1
Es un método para matrices con un rendimiento superior al de Enumerable desde v2.4
Andre Figueiredo
25

Todos esos resultados generan basura en un celoso intento de manejar más de dos argumentos. Me gustaría ver cómo funcionan en comparación con el buen ol:

def max (a,b)
  a>b ? a : b
end

que es, por cierto, mi respuesta oficial a tu pregunta.

Dave Morse
fuente
Hay algunos rumores que Ruby 2.4 está optimizando [a,b].max, pero aún no está claro si es más rápido que la implementación anterior. blog.bigbinary.com/2016/11/17/…
Dave Morse
2
esto es micro-optimización, ambos son muy rápidos, la diferencia es insignificante, ver punto de referencia: repl.it/@AndreFigueiredo/DearWeirdSweepsoftware
Andre Figueiredo
1
¿Este perfil tiene en cuenta el tiempo que se pasa en GC?
Dave Morse
20

Si necesita encontrar el máximo / mínimo de un hash, puede usar #max_byo#min_by

people = {'joe' => 21, 'bill' => 35, 'sally' => 24}

people.min_by { |name, age| age } #=> ["joe", 21]
people.max_by { |name, age| age } #=> ["bill", 35]
codificación aaron
fuente
20

Además de las respuestas proporcionadas, si desea convertir Enumerable # max en un método max que pueda invocar un número variable o argumentos, como en otros lenguajes de programación, puede escribir:

def max(*values)
 values.max
end

Salida:

max(7, 1234, 9, -78, 156)
=> 1234

Esto abusa de las propiedades del operador splat para crear un objeto de matriz que contenga todos los argumentos proporcionados, o un objeto de matriz vacío si no se proporcionaron argumentos. En el último caso, el método volverá nil, ya que devuelve llamar a Enumerable # max en un objeto de matriz vacío nil.

Si desea definir este método en el módulo matemático, esto debería hacer el truco:

module Math
 def self.max(*values)
  values.max
 end
end

Tenga en cuenta que Enumerable.max es, al menos, dos veces más lento en comparación con el operador ternario ( ?:) . Vea la respuesta de Dave Morse para un método más simple y rápido.

HamsterMuffin
fuente
¿Pero la reapertura de las clases y módulos estándar no se considera una mala práctica?
radiantshaw
-2
def find_largest_num(nums)
  nums.sort[-1]
end
Almokhtar bekkour
fuente
ordenar para encontrar el máximo / mínimo es un desperdicio; encontrar min / max es O (n), mientras que la clasificación es O (n log (n)).
Itamar Mushkin