Como encontrar um mínimo / máximo com Ruby

415

Eu quero usar min(5,10), ou Math.max(4,7). Existem funções para esse efeito no Ruby?

obuzek
fonte

Respostas:

723

Você pode fazer

[5, 10].min

ou

[4, 7].max

Eles vêm do módulo Enumerable , portanto, qualquer coisa que inclua Enumerableterá esses métodos disponíveis.

A v2.4 introduz os métodos own Array#mine Array#max, que são muito mais rápidos que os métodos do Enumerable porque ignoram as chamadas #each.

@nicholasklick menciona outra opção, Enumerable#minmaxmas desta vez retornando uma matriz de [min, max].

[4, 5, 7, 10].minmax
=> [4, 10]
theIV
fonte
3
@kaz Não sei se entendi o seu comentário.
Ziggy
3
@ Kaz ... você percebe que std::max(4, 7)tem mais "pontuação" do que [4, 7].max?
tckmn
3
@ Doorknob Você percebe que std::maxpode ser importado para o seu espaço para nome, então ele se torna max(4, 7). Esperar; olhando para cima, eu já disse isso.
Kaz
18
A pontuação não é o problema aqui. Uma alocação de heap inteira para obter o máximo de alguns valores é a feiúra subjacente aqui.
precisa saber é o seguinte
7
Ruby é principalmente para o programador e não para o computador. Nas palavras de Matz, "espero que Ruby ajude todos os programadores do mundo a serem produtivos, a gostar de programar e a serem felizes. Esse é o objetivo principal da linguagem Ruby". Isso é da página da Wikipedia em Ruby.
codificação aaron
52

Você pode usar

[5,10].min 

ou

[4,7].max

É um método para matrizes.

Diego Dias
fonte
20
Tecnicamente, é um método para Enumerables, não Arrays.
meagar
1
É um método para Arrays com desempenho superior ao longo Enumerable é desde v2.4
Andre Figueiredo
25

Todos esses resultados geram lixo em uma tentativa zelosa de lidar com mais de dois argumentos. Eu ficaria curioso para ver como eles se saem em comparação com o bom:

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

que é, a propósito, a minha resposta oficial à sua pergunta.

Dave Morse
fonte
Há alguns rumores de que o Ruby 2.4 está otimizando [a,b].max, mas ainda não está claro se é mais rápido que a implementação acima. blog.bigbinary.com/2016/11/17/…
Dave Morse
2
este é micro-otimização, ambos são tão rápido, a diferença é insignificante, veja referência: repl.it/@AndreFigueiredo/DearWeirdSweepsoftware
Andre Figueiredo
1
Essa criação de perfil leva em consideração o tempo gasto no GC?
Dave Morse
20

Se você precisar encontrar o máximo / min de um hash, poderá usar #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]
codificação aaron
fonte
20

Além das respostas fornecidas, se você quiser converter Enumerable # max em um método max que possa chamar um número ou argumentos variáveis, como em algumas outras linguagens de programação, você pode escrever:

def max(*values)
 values.max
end

Resultado:

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

Isso abusa das propriedades do operador splat para criar um objeto de matriz que contenha todos os argumentos fornecidos ou um objeto de matriz vazio se nenhum argumento for fornecido. Neste último caso, o método retornará nil, pois a chamada Enumerable # max em um objeto de matriz vazio será retornada nil.

Se você deseja definir esse método no módulo Math, faça o seguinte:

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

Observe que Enumerable.max é, pelo menos, duas vezes mais lento em comparação com o operador ternário ( ?:) . Veja a resposta de Dave Morse para um método mais simples e rápido.

HamsterMuffin
fonte
Mas a reabertura de classes e módulos padrão não é considerada uma prática ruim?
radiantshaw
-2
def find_largest_num(nums)
  nums.sort[-1]
end
Almokhtar bekkour
fonte
classificar para encontrar o máximo / mínimo é um desperdício; encontrar min / max é O (n), enquanto a classificação é O (n log (n)).
Itamar Mushkin 12/03