Comment trouver un min / max avec Ruby


415

Je veux utiliser min(5,10), ou Math.max(4,7). Existe-t-il des fonctions à cet effet dans Ruby?

Réponses:


723

Tu peux faire

[5, 10].min

ou

[4, 7].max

Ils proviennent du module Enumerable , donc tout ce qui inclut Enumerableaura ces méthodes disponibles.

La v2.4 introduit les méthodes propres Array#minet Array#max, qui sont bien plus rapides que les méthodes d'Enumerable car elles ignorent les appels #each.

@nicholasklick mentionne une autre option, Enumerable#minmaxmais cette fois en retournant un tableau de [min, max].

[4, 5, 7, 10].minmax
=> [4, 10]

3
@kaz Je ne suis pas sûr de comprendre votre commentaire.
Ziggy

3
@Kaz ... vous vous rendez compte qu'il y std::max(4, 7)a plus de "ponctuation" que [4, 7].max?
tckmn

3
@ Doorknob Vous vous rendez compte que cela std::maxpeut être importé dans votre espace de noms pour qu'il devienne juste max(4, 7). Attendre; en regardant ci-dessus, je vois que je l'ai déjà dit.
Kaz

18
La ponctuation n'est pas le problème ici. Une allocation de tas entière pour obtenir le maximum de quelques valeurs est la laideur sous-jacente ici.
kdbanman

7
Ruby est principalement destiné au programmeur et non à l'ordinateur. Selon les mots de Matz "J'espère voir Ruby aider tous les programmeurs du monde à être productifs, à profiter de la programmation et à être heureux. C'est le but principal du langage Ruby." Ça vient de la page Wikipedia sur Ruby.
codage aaron du

52

Vous pouvez utiliser

[5,10].min 

ou

[4,7].max

C'est une méthode pour les tableaux.


20
Techniquement, c'est une méthode pour les énumérables, pas les tableaux.
meagar

1
C'est une méthode pour les tableaux avec des performances supérieures à celles d'Enumerable depuis la v2.4
Andre Figueiredo

25

Tous ces résultats génèrent des ordures dans une tentative ardente de gérer plus de deux arguments. Je serais curieux de voir comment ils fonctionnent par rapport aux bons vieux:

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

qui est d'ailleurs ma réponse officielle à votre question.


Il y a quelques rumeurs que Ruby 2.4 optimise [a,b].max, mais il n'est toujours pas clair si c'est plus rapide que l'implémentation ci-dessus. blog.bigbinary.com/2016/11/17/…
Dave Morse

2
c'est de la micro-optimisation, ils sont tous les deux si rapides, la différence est négligeable, voir benchmark: repl.it/@AndreFigueiredo/DearWeirdSweepsoftware
Andre Figueiredo

1
Ce profilage tient-il compte du temps passé au GC?
Dave Morse

20

Si vous avez besoin de trouver le max / min d'un hachage, vous pouvez utiliser #max_byou#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]

20

En plus des réponses fournies, si vous souhaitez convertir Enumerable # max en une méthode max pouvant appeler un nombre variable ou des arguments, comme dans certains autres langages de programmation, vous pouvez écrire:

def max(*values)
 values.max
end

Production:

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

Cela abuse des propriétés de l'opérateur splat pour créer un objet tableau contenant tous les arguments fournis ou un objet tableau vide si aucun argument n'a été fourni. Dans ce dernier cas, la méthode retournera nil, car l'appel de Enumerable # max sur un objet tableau vide retourne nil.

Si vous souhaitez définir cette méthode sur le module Math, cela devrait faire l'affaire:

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

Notez que Enumerable.max est, au moins, deux fois plus lent que l'opérateur ternaire ( ?:) . Voir la réponse de Dave Morse pour une méthode plus simple et plus rapide.


Mais la réouverture des classes et modules standard n'est-elle pas considérée comme une mauvaise pratique?
radiantshaw

-2
def find_largest_num(nums)
  nums.sort[-1]
end

trier pour trouver le maximum / minimum est un gaspillage; trouver min / max est O (n), tandis que le tri est O (n log (n)).
Itamar Mushkin
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.