Jak znaleźć min / max za pomocą Ruby

415

Chcę użyć min(5,10)lub Math.max(4,7). Czy są funkcje tego efektu w Ruby?

obuzek
źródło

Odpowiedzi:

722

Możesz to zrobić

[5, 10].min

lub

[4, 7].max

Pochodzą z modułu Enumerable , więc wszystko, co obejmuje, Enumerablebędzie miało dostęp do tych metod.

Wersja 2.2 wprowadza własne Array#mini Array#max, które są znacznie szybsze niż metody Enumerable, ponieważ pomijają wywoływanie #each.

@nicholasklick wspomina o innej opcji, Enumerable#minmaxale tym razem zwraca tablicę [min, max].

[4, 5, 7, 10].minmax
=> [4, 10]
theIV
źródło
3
@kaz Nie jestem pewien, czy rozumiem twój komentarz.
Ziggy
3
@Kaz ... zdajesz sobie sprawę, że std::max(4, 7)ma więcej „interpunkcji” niż [4, 7].max?
tckmn
3
@Doorknob Zdajesz sobie sprawę, że std::maxmożna je zaimportować do przestrzeni nazw, aby po prostu się stało max(4, 7). Czekać; patrząc wyżej widzę, że już to powiedziałem.
Kaz
18
Interpunkcja nie jest tutaj problemem. Cały przydział sterty, aby uzyskać maksymalnie kilka wartości, jest tutaj brzydotą.
kdbanman,
7
Ruby jest przeznaczony głównie dla programisty, a nie dla komputera. Słowami Matza: „Mam nadzieję, że Ruby pomoże każdemu programistowi na świecie, aby był produktywny, czerpał przyjemność z programowania i był szczęśliwy. To jest główny cel języka Ruby”. To ze strony Wikipedii na Ruby.
kodowanie
52

Możesz użyć

[5,10].min 

lub

[4,7].max

To metoda tablic.

Diego Dias
źródło
20
Technicznie jest to metoda dla Wyliczeń, a nie Tablic.
Meagar
1
Jest to metoda dla tablic o lepszej wydajności niż Enumerable od wersji 2.4
Andre Figueiredo
25

Wszystkie te wyniki generują śmieci w gorliwej próbie obsłużenia więcej niż dwóch argumentów. Byłbym ciekawy, jak wypadają w porównaniu z dobrym „olem”:

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

tak przy okazji, moja oficjalna odpowiedź na twoje pytanie.

Dave Morse
źródło
Istnieją pewne pomruki, które Ruby 2.4 optymalizuje [a,b].max, ale nadal nie jest jasne, czy jest szybsze niż powyższa implementacja. blog.bigbinary.com/2016/11/17/…
Dave Morse
2
jest to mikrooptymalizacja, obie są tak szybkie, różnica jest znikoma, patrz test: repl.it/@AndreFigueiredo/DearWeirdSweepsoftware
Andre Figueiredo
1
Czy to profilowanie uwzględnia czas spędzony w GC?
Dave Morse
20

Jeśli chcesz znaleźć maks / min skrótu, możesz użyć #max_bylub#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]
kodowanie Aarona
źródło
20

Oprócz podanych odpowiedzi, jeśli chcesz przekonwertować Enumerable # max na metodę max, która może wywoływać zmienną liczbę lub argumenty, jak w niektórych innych językach programowania, możesz napisać:

def max(*values)
 values.max
end

Wynik:

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

Narusza to właściwości operatora splat do tworzenia obiektu tablicowego zawierającego wszystkie podane argumenty lub pustego obiektu tablicowego, jeśli nie podano argumentów. W drugim przypadku metoda zwróci nil, ponieważ zwracane jest wywołanie Enumerable # max na pustym obiekcie tablicy nil.

Jeśli chcesz zdefiniować tę metodę w module Math, powinno to załatwić sprawę:

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

Zauważ, że Enumerable.max jest co najmniej dwa razy wolniejszy w porównaniu do operatora trójskładnikowego ( ?:) . Zobacz odpowiedź Dave'a Morse'a na prostszą i szybszą metodę.

HamsterMuffin
źródło
Ale czy ponowne otwarcie standardowych klas i modułów nie jest uważane za złą praktykę?
radiantshaw
-2
def find_largest_num(nums)
  nums.sort[-1]
end
Almokhtar bekkour
źródło
sortowanie w celu znalezienia maksimum / minimum jest marnotrawstwem; znalezienie min / max to O (n), podczas gdy sortowanie to O (n log (n)).
Itamar Mushkin