Jak mogę łatwo uzyskać min. Lub maks. Element tablicy JavaScript?
Przykładowy kod Psuedocode:
let array = [100, 0, 50]
array.min() //=> 0
array.max() //=> 100
javascript
Hank
źródło
źródło
...
) zMath.max()
tak:Math.max(...[2, 5, 16, 1])
. Zobacz moją odpowiedź wykonany z dokumentacją MDN .Math.max.apply(null, [2,5,16,1])
Odpowiedzi:
Co powiesz na rozszerzenie wbudowanego obiektu Array do użycia
Math.max
/Math.min
zamiast:Oto JSFiddle .
Rozszerzanie wbudowanych może powodować kolizje z innymi bibliotekami (niektóre patrz), więc możesz czuć się bardziej komfortowo z bezpośrednim
apply
dostępemMath.xxx()
do tablicy:Alternatywnie, zakładając, że Twoja przeglądarka obsługuje ECMAScript 6, możesz użyć operatora rozprzestrzeniania, który działa podobnie do
apply
metody:źródło
null
lubMath
lub{}
lub cokolwiek sięapply()
lubcall()
nie ma wpływu na wynik.Math.max
nie odnosi się ani nie powinien odnosić sięthis
wewnętrznie.Math.max.apply(null, $.makeArray(array));
.max
lub.min
metody w przyszłości. Idealnie realistyczny scenariusz: korzystasz z tej odpowiedzi. W 2016 r. Specyfikacja ES7 lub ES8Array.max
iArray.min
. W przeciwieństwie do tej wersji działają na ciągach znaków. Twój przyszły kolega próbuje pobrać najnowszy alfabetyczny ciąg do tablicy za pomocą dobrze udokumentowanej.max()
metody natywnej , ale w tajemniczy sposóbNaN
. Kilka godzin później znajduje ten kod, uruchamiagit blame
i przeklina twoje imię.Pełna dyskusja na stronie: http://aaroncrane.co.uk/2008/11/javascript_max_api/
źródło
Math.max.apply(Math, array)
iMath.max.apply(null, array)
? Na blogu jest napisane: „… musisz także powtórnie powiedzieć, żemax
należy doMath
…”, ale wydaje się, że nie muszę tego robić (ustawiając pierwszy argumentapply
asnull
).Math.max(a,b)
,Math
jest on przekazywany jakothis
wartość, więc może to mieć sens, aby robić to samo, dzwoniąc zapply
. AleMath.max
nie używa tejthis
wartości, więc możesz przekazać dowolną wartość, którą chcesz.Dla dużych tablic (~ 10⁷ elementów)
Math.min
iMath.max
oba powodują następujący błąd w Node.js.Bardziej niezawodnym rozwiązaniem jest nie dodawanie każdego elementu do stosu wywołań, ale zamiast tego przekazywanie tablicy:
Jeśli obawiasz się o szybkość, poniższy kod jest ~ 3 razy szybszy niż
Math.max.apply
na moim komputerze. Zobacz http://jsperf.com/min-and-max-in-array/2 .Jeśli twoje tablice zawierają ciągi zamiast liczb, musisz również zmusić je do liczb. Poniższy kod to robi, ale spowalnia kod ~ 10 razy na moim komputerze. Zobacz http://jsperf.com/min-and-max-in-array/3 .
źródło
min
imax
do ostatniego elementu i zmniejsz iteracje o 1 (while(--len)
);)very different results
zrobiłeś to 5 lat później)reduce
Rozwiązanie jest najwolniejsze. Nawet jeśli pracujesz z tablicą zawierającą miliony elementów, lepiej jest użyć standardowej pętli for . Zobacz moją odpowiedź, aby uzyskać więcej.Korzystanie z operatora rozkładania (ES6)
Pokaż fragment kodu
źródło
If no arguments are given, the result is -∞.
tl; dr
Rozwiązanie MDN
W oficjalnych Docs MDN na
Math.max()
obejmuje już ten problem:Maksymalny rozmiar tablicy
Według MDN się
apply
i rozprzestrzeniania rozwiązań miało ograniczenie 65536 dostarczonej z limitem maksymalnej liczby argumentów:Zapewniają nawet rozwiązanie hybrydowe, które tak naprawdę nie ma dobrej wydajności w porównaniu z innymi rozwiązaniami. Zobacz test wydajności poniżej, aby uzyskać więcej.
W 2019 r. Rzeczywisty limit to maksymalny rozmiar stosu wywołań . W przypadku nowoczesnych przeglądarek stacjonarnych opartych na Chromium oznacza to, że jeśli chodzi o znalezienie min / max z
apply
lub rozprzestrzeniania, praktycznie maksymalny rozmiar dla tablic tylko z liczbami wynosi ~ 120000 . Ponadto nastąpi przepełnienie stosu i zostanie zgłoszony następujący błąd:Za pomocą poniższego skryptu (na podstawie tego postu na blogu ), wychwytując ten błąd, możesz obliczyć limit dla określonego środowiska.
Ostrzeżenie! Uruchomienie tego skryptu zajmuje dużo czasu i w zależności od wydajności systemu może spowolnić lub zawiesić przeglądarkę / system!
Wydajność na dużych tablicach
W oparciu o test w komentarzu EscapeNetscape stworzyłem pewne testy porównawcze, które testują 5 różnych metod na tablicy z liczbami losowymi zawierającymi 100 000 elementów .
W 2019 r. Wyniki pokazują, że standardowa pętla (której BTW nie ma ograniczenia wielkości) jest wszędzie najszybsza.
apply
i rozprzestrzenia się po nim, a potem znacznie później hybrydowe rozwiązanie MDNreduce
jako najwolniejsze.Prawie wszystkie testy dały takie same wyniki, z wyjątkiem jednego, w którym rozprzestrzenianie się okazało się być najwolniejsze.
Jeśli zwiększysz swoją tablicę, aby mieć milion przedmiotów, wszystko zacznie się psuć i pozostanie Ci standardowa pętla jako szybkie rozwiązanie i
reduce
wolniejsze.Test porównawczy JSPerf
Test porównawczy JSBen
Test porównawczy JSBench.me
Kod źródłowy testu porównawczego
Pokaż fragment kodu
źródło
Math.max.apply(Math, arr)
zapewnienia zgodności z „maksymalnym”.(...)
iapply
niepowodzenie lub zwrócenie niewłaściwego wyniku, jeśli tablica zawiera zbyt wiele elementów [...] Rozwiązanie redukujące nie ma tego problemu” Testowanie Chrome, FF, Edge i IE11 wydaje się, że jest ok dla tablicy do 100k wartości. (Testowane na Win10 i najnowszych przeglądarkach: Chrome 110k, Firefox 300k, Edge 400k, IE11 150k).Jeśli masz paranoję na punkcie używania
Math.max.apply
(co może powodować błędy przy podawaniu dużych tablic zgodnie z MDN ), spróbuj tego:Lub w ES6:
Funkcje anonimowe są niestety konieczne (zamiast używać,
Math.max.bind(Math)
ponieważreduce
nie tylko przekazująa
ib
do jej funkcji, ale takżei
i odniesienia do samej tablicy, więc musimy upewnić się, że nie próbujemy też wywoływaćmax
tych funkcji).źródło
Math.max(...array)
?apply
, i dlatego ma takie same wady (maksymalny limit argumentów).function arrayMax(array) { return array.reduce(function(a, b) { return Math.max(a, b); }); // <--------- missing ) }
Math.min()
bez wartości, zwracaInfinity
, więc te funkcje mogłyby zostać użytereduce(..., Infinity)
do dopasowania tego zachowania. Wolę jednak, aby generował wyjątek (jak ma to miejsce obecnie), ponieważ przyjmowanie minimum pustej tablicy wydaje się być błędem..apply
jest często używany, gdy celem jest wywołanie funkcji variadic z listą wartości argumentów, npMath.max([value1[,value2, ...]])
Zwraca największą zero lub więcej cyfr.Ta
Math.max()
metoda nie pozwala przekazać w tablicy. Jeśli masz listę wartości, które musisz uzyskać największą, zwykle wywoływałbyś tę funkcję za pomocą Function.prototype.apply () , np.Jednak od ECMAScript 6 można używać operatora rozkładania :
Za pomocą operatora rozkładania powyższe można przepisać jako takie:
Podczas wywoływania funkcji za pomocą operatora variadic można nawet dodać dodatkowe wartości, np
Premia:
Operator spread umożliwia użycie składni dosłownego tablicy do tworzenia nowych tablic w sytuacjach, gdy w ES5 trzeba by spaść z powrotem do kodu imperatyw, używając kombinacji
push
,splice
itpźródło
concat
większości programistów, ponieważ pozwala zachować pojedynczy styl linii.Dwa sposoby są krótsze i łatwiejsze:
Sposób 1 :
Sposób 2 :
źródło
0
, możesz użyć[0].concat(arr)
lub ze składnią rozprzestrzeniania[0, ...arr]
(zamiast „arr”)Robisz to poprzez rozszerzenie typu Array:
Wzmocniony stąd (autor: John Resig)
źródło
Prostym rozwiązaniem w celu znalezienia minimalnej wartości nad jednym
Array
z elementów jest użycieArray
funkcji prototypowejreduce
:lub za pomocą wbudowanej w JavaScript funkcji Math.Min () (dzięki @Tenflex):
Spowoduje
min
to ustawienieA[0]
, a następnie sprawdzenie,A[1]...A[n]
czy wartość jest ściśle mniejsza niż bieżącamin
. JeśliA[i] < min
następniemin
jest zaktualizowany doA[i]
. Po przetworzeniu wszystkich elementów tablicymin
jest zwracany jako wynik.EDYCJA : Uwzględnij pozycję o minimalnej wartości:
źródło
min
wartość, ale także jej pozycję w tablicy?Inni podali już pewne rozwiązania, w których się rozszerzają
Array.prototype
. Chcę tylko w tej odpowiedzi wyjaśnić, czy powinna być,Math.min.apply( Math, array )
czy teżMath.min.apply( null, array )
. Więc w jakim kontekście należy użyćMath
lubnull
?W przypadku przekazania
null
jako kontekstuapply
kontekstem domyślnym jest obiekt globalny (window
obiekt w przypadku przeglądarek). PodanieMath
obiektu jako kontekstu byłoby właściwym rozwiązaniem, ale nie zaszkodzi to również podaniunull
. Oto przykład, kiedynull
może powodować problemy podczas dekorowaniaMath.max
funkcji:Powyższe spowoduje zgłoszenie wyjątku, ponieważ
this.foo
zostanie ocenione jakowindow.foo
, co jestundefined
. Jeśli zastąpimynull
zMath
rzeczy będzie działać zgodnie z oczekiwaniami, a łańcuch „foo” będzie wyświetlane na ekranie (I przetestowane przy użyciu Mozilla Rhino ).Można prawie założyć, że nikt nie udekorował,
Math.max
więc przejścienull
będzie działać bez problemów.źródło
Foo.staticMethod
i odwoływać sięthis
? Czy nie byłby to błąd w projekcie dekoratora? (chyba że oczywiście chcą się odwołać zasięg globalny, i chce pozostać niezależny od silnika JavaScript jest używany, np Rhino).Math.max
, zaimplementowane zgodnie ze specyfikacją, nie używathis
. Jeśli ktoś nadpisujeMath.max
takie, że używathis
, oznacza to, że jego zachowanie narusza specyfikację i należy rzucać w nie ostrymi przedmiotami. Nie powinieneś kodować wokół tej możliwości bardziej niż kodowałbyś wokół możliwości, że ktoś zamienił sięMath.max
iMath.min
na lulz.Jeszcze jeden sposób, aby to zrobić:
Stosowanie:
źródło
Alternatywne metody
Math.min
IMath.max
metody są obie operacje rekurencyjne, które są dodawane do wywołania stosu silnika JS, a najprawdopodobniej krach na tablicy, która zawiera dużą liczbę elementów(więcej niż ~ 10⁷ przedmioty, zależy od przeglądarki użytkownika).
Zamiast tego użyj czegoś takiego:
Lub z lepszym czasem działania:
Lub uzyskać zarówno Min i Max:
Lub z jeszcze lepszym czasem pracy *:
* Testowany z 1 000 000 elementów:
Dla porównania, czas działania pierwszej funkcji (na mojej maszynie) wyniósł 15,84 ms w porównaniu z drugą funkcją tylko 4,32 ms.
źródło
Może to pasować do twoich celów.
źródło
comparer
należy wywoływać w określonym zakresie? Ponieważ jak to jest odniesienia,this[index]
które sąundefined
za każdym razem.Math.xxx
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math/max
to zadziałało dla mnie.
źródło
Dziwi mnie, że nikt nie wspomniał o funkcji redukcji.
źródło
Dla dużych tablic (~ 10⁷ elementów)
Math.min
iMath.max
wywołuje błąd RangeError (przekroczony maksymalny rozmiar stosu wywołań) w node.js.W przypadku dużych tablic szybkim i brudnym rozwiązaniem jest:
źródło
Miałem ten sam problem, musiałem uzyskać minimalne i maksymalne wartości tablicy i, ku mojemu zaskoczeniu, nie było wbudowanych funkcji tablic. Po długim czytaniu postanowiłem sam przetestować „najlepsze 3” rozwiązania:
Kod testowy był następujący:
Tablica A została wypełniona 100 000 losowych liczb całkowitych, każda funkcja była wykonywana 10 000 razy w Mozilla Firefox 28.0 na komputerze Intel Pentium 4 2,99 GHz z systemem Windows Vista. Czasy podano w sekundach, pobierane przez funkcję performance.now (). Wyniki były następujące, z 3 cyframi ułamkowymi i odchyleniem standardowym:
Rozwiązanie REDUCE było 117% wolniejsze niż rozwiązanie dyskretne. Rozwiązanie APPLY było gorsze, o 2118% wolniejsze niż rozwiązanie dyskretne. Poza tym, jak zauważył Peter, nie działa w przypadku dużych tablic (około 1 000 000 elementów).
Ponadto, aby ukończyć testy, przetestowałem ten rozszerzony dyskretny kod:
Czas: średnia = 0,218s, sd = 0,094
Jest więc o 35% wolniejszy niż proste rozwiązanie dyskretne, ale pobiera zarówno wartości maksymalne, jak i minimalne naraz (każde inne rozwiązanie wymagałoby co najmniej dwukrotności tego, aby je odzyskać). Gdy OP potrzebowałby obu wartości, rozwiązaniem dyskretnym byłby najlepszy wybór (nawet jako dwie osobne funkcje, jedna do obliczania maksimum, a druga do obliczania minimum, przewyższałyby drugie najlepsze rozwiązanie ZREDUKUJ).
źródło
Możesz użyć następującej funkcji w dowolnym miejscu w swoim projekcie:
Następnie możesz wywołać funkcje przekazujące tablicę:
źródło
Poniższy kod działa dla mnie:
źródło
Iteruj, śledząc cały czas.
Spowoduje to pozostawienie wartości min / max null, jeśli w tablicy nie ma żadnych elementów. Ustawi min i max w jednym przejściu, jeśli tablica zawiera jakieś elementy.
Możesz także rozszerzyć tablicę za pomocą
range
metody wykorzystującej powyższe, aby umożliwić ponowne użycie i poprawić czytelność. Zobacz działające skrzypce na http://jsfiddle.net/9C9fU/Użyty jako
źródło
range
funkcji na funkcję, która byłaby najlepszym sposobem na uzyskanie zarówno minimalnej, jak i maksymalnej wartości w tym samym czasie IMO - tak jak zrobiłem z aktualizacją mojej odpowiedzi.Myślałem, że podzielę się moim prostym i łatwym do zrozumienia rozwiązaniem.
Za min .:
A dla maksimum:
źródło
for…in
wyliczeń na tablicach!Oprócz korzystania z funkcji matematycznych max i min, inną funkcją do użycia jest wbudowana funkcja sort (): proszę bardzo
źródło
Proste rzeczy, naprawdę.
źródło
Oto jeden ze sposobów uzyskania maksymalnej wartości z tablicy obiektów. Utwórz kopię (z plasterkiem), a następnie posortuj kopię w porządku malejącym i chwyć pierwszy element.
źródło
Za pomocą
Math.max()
lubMath.min()
Poniższa funkcja służy
Function.prototype.apply()
do znalezienia maksymalnego elementu w tablicy numerycznej.getMaxOfArray([1, 2, 3])
jest równoważneMath.max(1, 2, 3)
, ale można używaćgetMaxOfArray()
na programowo skonstruowanych tablicach o dowolnym rozmiarze.Lub dzięki nowemu operatorowi rozkładania uzyskanie maksimum tablicy staje się znacznie łatwiejsze.
źródło
Rozwiązanie ChaosPandion działa, jeśli używasz protoype. Jeśli nie, rozważ to:
Powyższe zwróci NaN, jeśli wartość tablicy nie jest liczbą całkowitą, dlatego należy zbudować pewną funkcjonalność, aby tego uniknąć. W przeciwnym razie to zadziała.
źródło
Math
obiektu jako kontekstu?Jeśli korzystasz z biblioteki sugar.js , możesz pisać arr.min () i arr.max (), jak sugerujesz. Można także uzyskać wartości minimalne i maksymalne z tablic nienumerycznych.
Przykłady:
Biblioteki takie jak Lo-Dash i underscore.js zapewniają również podobne zaawansowane funkcje min i max:
Przykład z Lo-Dash:
źródło
źródło
Próbować
Pokaż fragment kodu
Dla Math.min / max (+ Apply) otrzymujemy błąd:
Pokaż fragment kodu
źródło