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.