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?

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]

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.


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.


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]

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.


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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.