Come trovare un min / max con Ruby


415

Voglio usare min(5,10), o Math.max(4,7). Ci sono funzioni per questo effetto in Ruby?

Risposte:


723

Tu puoi fare

[5, 10].min

o

[4, 7].max

Provengono dal modulo Enumerable , quindi tutto ciò che include Enumerableavrà quei metodi disponibili.

v2.4 introduce proprio Array#mine Array#max, che sono molto più veloci dei metodi di Enumerable perché saltano la chiamata #each.

@nicholasklick menziona un'altra opzione, Enumerable#minmaxma questa volta restituisce un array di [min, max].

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

3
@kaz Non sono sicuro di aver capito il tuo commento.
Ziggy,

3
@Kaz ... ti rendi conto che std::max(4, 7)ha più "punteggiatura" di [4, 7].max?
martedì

3
@Doorknob Ti rendi conto che std::maxpuò essere importato nel tuo spazio dei nomi in modo che diventi max(4, 7). Aspettare; guardando sopra, vedo che l'ho già detto.
Kaz

18
La punteggiatura non è il problema qui. Un'intera allocazione di heap per ottenere il massimo di alcuni valori è la bruttezza sottostante qui.
kdbanman,

7
Ruby è principalmente per il programmatore, non per il computer. Nelle parole di Matz "Spero di vedere Ruby aiutare tutti i programmatori del mondo a essere produttivi, a godersi la programmazione e ad essere felici. Questo è lo scopo principale del linguaggio Ruby". Viene dalla pagina di Wikipedia su Ruby.
codifica in aaron il

52

Puoi usare

[5,10].min 

o

[4,7].max

È un metodo per array.


20
Tecnicamente è un metodo per Enumerables, non per array.
meagar

1
È un metodo per array con prestazioni superiori rispetto a Enumerable dalla v2.4
Andre Figueiredo,

25

Tutti questi risultati generano immondizia nel tentativo zelante di gestire più di due argomenti. Sarei curioso di vedere come si comportano rispetto al buon vecchio:

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

che è, tra l'altro, la mia risposta ufficiale alla tua domanda.


Ci sono alcuni rumori che Ruby 2.4 sta ottimizzando [a,b].max, ma non è ancora chiaro se sia più veloce dell'implementazione di cui sopra. blog.bigbinary.com/2016/11/17/…
Dave Morse,

2
questa è micro-ottimizzazione, sono entrambi così veloci, la differenza è trascurabile, vedi benchmark: repl.it/@AndreFigueiredo/DearWeirdSweepsoftware
Andre Figueiredo

1
Questa profilazione tiene conto del tempo trascorso in GC?
Dave Morse,

20

Se devi trovare il massimo / minimo di un hash, puoi usare #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]

20

Oltre alle risposte fornite, se si desidera convertire Enumerable # max in un metodo max che può chiamare un numero variabile o argomenti, come in altri linguaggi di programmazione, è possibile scrivere:

def max(*values)
 values.max
end

Produzione:

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

Ciò abusa delle proprietà dell'operatore splat per creare un oggetto array contenente tutti gli argomenti forniti o un oggetto array vuoto se non sono stati forniti argomenti. In quest'ultimo caso, verrà restituito il metodo nil, poiché viene restituita la chiamata Enumerable # max su un oggetto array vuoto nil.

Se vuoi definire questo metodo sul modulo Math, questo dovrebbe fare il trucco:

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

Si noti che Enumerable.max è almeno due volte più lento rispetto all'operatore ternario ( ?:) . Vedi la risposta di Dave Morse per un metodo più semplice e veloce.


Ma la riapertura di classi e moduli standard non è considerata una cattiva pratica?
radiantshaw,

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

l'ordinamento per trovare il massimo / minimo è dispendioso; trovare min / max è O (n), mentre l'ordinamento è O (n log (n)).
Itamar Mushkin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.