Jak mogę znaleźć największą liczbę zawartą w tablicy JavaScript?

206

Mam prosty obiekt JavaScript Array zawierający kilka liczb.

[267, 306, 108]

Czy istnieje funkcja, która znalazłaby największą liczbę w tej tablicy?

rozsiany
źródło
22
Math.max(...[267, 306, 108]);
Jacksonkr

Odpowiedzi:

315

Resig na ratunek:

Array.max = function( array ){
    return Math.max.apply( Math, array );
};

Ostrzeżenie : ponieważ maksymalna liczba argumentów jest tak mała jak 65535 na niektórych maszynach wirtualnych , użyj pętli for, jeśli nie masz pewności, że tablica jest tak mała.

Półksiężyc Świeży
źródło
15
Ach, ale teraz ma na nim naklejkę jakości SO tylko w nieco krzywy sposób!
Shog9
2
FWIW, jeśli wydajność jest czynnikiem w twoim rozwiązaniu, przetestowałbym to w porównaniu z twoją łatwą do zakodowania funkcją, aby upewnić się, że działa dobrze. Zakładamy, że natywna implementacja będzie szybsza; w rzeczywistości koszt applypołączenia może to bardzo łatwo zmyć.
TJ Crowder,
2
Co jeśli moja długość tablicy jest większa niż limit liczby parametrów?
lukas.pukenis
3
@CrescentFresh zgodnie z tym: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... jest na stałe zakodowany w 65535. Zgodnie z tym: code.google.com/p/v8/issues/detail?id = 172 i wiedząc, że argumenty są wypychane na stos, wiemy, że nie jest to nieograniczone
lukas.pukenis,
9
Ponadto ta metoda nie jest niezawodna. Nie powiedzie się, jeśli twoja tablica jest większa niż mamximum stosu, co powodujeRangeError: Maximum call stack size exceeded.
Mark Lundin
197

Możesz użyć funkcji Apply , aby wywołać Math.max :

var array = [267, 306, 108];
var largest = Math.max.apply(Math, array); // 306

Jak to działa?

zastosowanie służy do wywoływania innej funkcji z danym kontekstem i argumentami podanymi w postaci tablicy. Funkcje min i max mogą przyjmować dowolną liczbę argumentów wejściowych: Math.max (val1, val2, ..., valN)

Więc jeśli zadzwonimy:

Math.min.apply(Math, [1,2,3,4]);

Funkcja Apply wykona:

Math.min(1,2,3,4);

Zauważ, że pierwszy parametr, kontekst, nie jest ważny dla tych funkcji, ponieważ są one statyczne, będą działać niezależnie od tego, co zostanie przekazane jako kontekst.

CMS
źródło
2
Whoa, wkładasz swoje odpowiedzi z dużym wysiłkiem: D
ShrekOverflow 26.09.12
1
To wspaniale. Ale co jeśli moja długość tablicy przekracza limit wielkości parametru (funkcji)? Co wtedy ?
lukas.pukenis
1
Podoba mi się ta odpowiedź bardziej niż inne, ponieważ wyjaśnia, co robi wszystko i dlaczego. +1
Marvin,
59

Najłatwiejsza składnia z nowym operatorem rozkładania :

var arr = [1, 2, 3];
var max = Math.max(...arr);

Źródło: Mozilla MDN

AI
źródło
2
Jednak zarówno spread (...), jak i appl albo się nie powiedzie, albo zwróci nieprawidłowy wynik, jeśli tablica zawiera zbyt wiele elementów developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Green
@Green FWIW, limit liczby parametrów wynosi 65536 (przynajmniej w Chrome) ([źródło ( bugs.webkit.org/show_bug.cgi?id=80797)] ). Więc jeśli twoja tablica zawiera więcej niż 65536 elementów, ta odpowiedź nie zadziała.
mgthomas99
4
65536 powinno wystarczyć dla każdego
vsync
41

Nie jestem ekspertem od JS, ale chciałem zobaczyć, jak te metody się nakładają, więc była to dla mnie dobra praktyka. Nie wiem, czy jest to technicznie właściwy sposób na przetestowanie ich wydajności, ale po prostu uruchomiłem je jeden po drugim, jak widać w moim kodzie.

Sortowanie i uzyskiwanie wartości 0 jest zdecydowanie najgorszą metodą (i modyfikuje kolejność tablicy, co może nie być pożądane). Dla pozostałych różnica jest znikoma, chyba że mówimy o milionach wskaźników.

Średnie wyniki pięciu przebiegów z tablicą liczb losowych o wartości 100 000 indeksów:

  • zmniejszyć miały 4.0392ms uruchomić
  • Math.max.apply wziął 3.3742ms uruchomić
  • Sortowanie i uzyskiwanie wartość 0-cia wziął 67.4724ms uruchomić
  • Uruchomienie Math.max w funkcji replace () zajęło 6.5804ms
  • zwyczaj funkcja findmax wziął 1.6102ms uruchomić

var performance = window.performance

function findmax(array)
{
  var max = 0,
      a = array.length,
      counter

  for (counter=0;counter<a;counter++)
  {
      if (array[counter] > max)
      {
          max = array[counter]
      }
  }
  return max
}

function findBiggestNumber(num) {
  var counts = []
  var i
  for (i = 0; i < num; i++) {
    counts.push(Math.random())
  }

  var a, b

  a = performance.now()
  var biggest = counts.reduce(function(highest, count){
        return highest > count ? highest : count
      }, 0)
  b = performance.now()
  console.log('reduce took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest2 = Math.max.apply(Math, counts)
  b = performance.now()
  console.log('Math.max.apply took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest3 = counts.sort(function(a,b){return b-a;})[0]
  b = performance.now()
  console.log('sorting and getting the 0th value took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest4 = counts.reduce(function(highest, count){
        return Math.max(highest,count)
      }, 0)
  b = performance.now()
  console.log('Math.max within reduce() took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest5 = findmax(counts)
  b = performance.now()
  console.log('custom findmax function took ' + (b - a) + ' ms to run')
  console.log(biggest + '-' + biggest2 + '-' + biggest3 + '-' + biggest4 + '-' + biggest5)

}

findBiggestNumber(1E5)
redOctober13
źródło
7
Dla mnie to najlepsza odpowiedź na to pytanie.
rzelek
1
Zrobiłem jsperf testsdla powyższego
vsync
37

Przekonałem się, że w przypadku większych tablic (~ 100 000 elementów) opłaca się po prostu iterować tablicę skromną forpętlą, osiągając ~ 30% lepiej niż Math.max.apply():

function mymax(a)
{
    var m = -Infinity, i = 0, n = a.length;

    for (; i != n; ++i) {
        if (a[i] > m) {
            m = a[i];
        }
    }

    return m;
}

Wyniki testu

Jacek
źródło
3
FWIW, teraz wychodzi na 84% w Chrome 31.
Ilan Biala
31

Możesz posortować tablicę w kolejności malejącej i uzyskać pierwszy element:

[267, 306, 108].sort(function(a,b){return b-a;})[0]
Gumbo
źródło
4
Zakładam, że możesz również posortować i zdobyć ostatni przedmiot ...?
Shog9
@ Shog9: Tak, ale musisz sam określić funkcję porównania:sort(function(a,b){return b-a;})
Gumbo,
9
Ach Myślałem bardziej jak:[...].sort().pop()
Shog9
4
„znalezienie liczby zajmuje kolejność-n, sortowanie odbywa się między kolejnością (n log n) do kolejności (n-kwadrat), w zależności od zastosowanego algorytmu sortowania” - webmasterworld.com/forum91/382.htm
Marco Luglio
2
Należy również pamiętać, że sortuje to tablicę, co może być pożądanym skutkiem ubocznym. Zastosuj rozwiązanie jest bardziej skuteczne i nie ma skutków ubocznych.
Caleb
28

Co powiesz na to:

var arr = [1,2,3,4];

var largest = arr.reduce(function(x,y){
       return (x > y) ? x : y;
});

console.log(largest);
brroshan
źródło
Gdybym pierwszy raz zobaczył tę odpowiedź (obecnie na dole listy), zaoszczędziłbym dwie godziny.
user139301
1
Podejście Math.max jest prawdopodobnie najbardziej standardowe, ale dostałem przepełnienie stosu, gdy tablica była zbyt duża (500 KB). Ta odpowiedź jest szybka i skuteczna i to właśnie z niej skorzystałem, więc poprawiam tę.
Jay
8

co powiesz na użycie Array.reduce ?

[0,1,2,3,4].reduce(function(previousValue, currentValue){
  return Math.max(previousValue,currentValue);
});
CodeToad
źródło
Wartość początkowa powinna być ustawiona na -Infinity.
Ja͢ck
@Jack, dlaczego jest to potrzebne? nawet z tablicą wszystkich liczb ujemnych otrzymuję prawidłowy wynik.
CodeToad,
1
Jest to przypadek skrajny, w którym tablica jest pusta.
Ja͢ck
5

Wykorzystują prawie wszystkie odpowiedzi Math.max.apply() co jest miłe i eleganckie, ale ma ograniczenia.

Argumenty funkcji są umieszczane na stosie, który ma wadę - limit. Więc jeśli twoja tablica jest większa niż limit, nie powiedzie sięRangeError: Maximum call stack size exceeded.

Aby znaleźć rozmiar stosu wywołań, użyłem tego kodu:

var ar = [];
for (var i = 1; i < 100*99999; i++) {
  ar.push(1);
  try {
    var max = Math.max.apply(Math, ar);
  } catch(e) {
    console.log('Limit reached: '+i+' error is: '+e);
    break;
  }
}

Okazało się, że jest największy w FireFoxie na moim komputerze - 591519 . Oznacza to, że jeśli tablica zawiera więcej niż 591519 elementów, Math.max.apply()wystąpi błąd RangeError .

Najlepszym rozwiązaniem tego problemu jest sposób iteracyjny (kredyt: https://developer.mozilla.org/ ):

max = -Infinity, min = +Infinity;

for (var i = 0; i < numbers.length; i++) {
  if (numbers[i] > max)
    max = numbers[i];
  if (numbers[i] < min)
    min = numbers[i];
}

O tym pytaniu pisałem tutaj na moim blogu .

lukas.pukenis
źródło
1
To niesprawiedliwe. Chcę odpowiedzi tutaj, na SO, a nie innego linku do innego zasobu strony trzeciej. Zwłaszcza gdy łączy się to z „wszystko tutaj jest złe, ale idź, spójrz, to jest świetne na moim blogu ...”
osa
@SergeyOrshanskiy link do strony trzeciej działa bardzo dobrze, jeśli zostanie zaktualizowany o nowe informacje i rozwiązania. Nie musisz się też obrażać. Ludzie też chcą rozwiązać twoje problemy. Też chciałem to rozwiązać, więc napisałem o tym na moim blogu
lukas.pukenis,
5

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max

const inputArray = [ 1, 3, 4, 9, 16, 2, 20, 18];
const maxNumber = Math.max(...inputArray);
console.log(maxNumber);

Abhijeet
źródło
2
Jednak zarówno spread (...), jak i appl albo się nie powiedzie, albo zwróci nieprawidłowy wynik, jeśli tablica zawiera zbyt wiele elementów developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Green
5

Znalezienie wartości maksymalnej i minimalnej jest łatwe i ręczne. Ten kod jest znacznie szybszy niż Math.max.apply; Próbowałem do 1000 000 numerów w tablicy.

function findmax(array)
{
    var max = 0;
    var a = array.length;
    for (counter=0;counter<a;counter++)
    {
        if (array[counter] > max)
        {
            max = array[counter];
        }
    }
    return max;
}

function findmin(array)
{
    var min = array[0];
    var a = array.length;
    for (counter=0;counter<a;counter++)
    {
        if (array[counter] < min)
        {
            min = array[counter];
        }
    }
    return min;
}
Yaser Ranjha
źródło
findmax()daje zły wynik, jeśli w tablicy są tylko liczby ujemne; findmin()daje zły wynik dla pustej tablicy.
Ja͢ck
3

Tak, oczywiście, istnieją: Math.max.apply(null,[23,45,67,-45]) i wynik zwraca 67;

użytkownik3702000
źródło
3

Prosta jedna wkładka

[].sort().pop()
Yasir Azgar
źródło
1

Nie zapomnij, że można zrobić okład z Function.prototype.bind, co daje „all-native” funkcji .

var aMax = Math.max.apply.bind(Math.max, Math);
aMax([1, 2, 3, 4, 5]); // 5
Paul S.
źródło
1

Możesz także rozszerzyć Arraytę funkcję i uczynić ją częścią każdej tablicy.

Array.prototype.max = function(){return Math.max.apply( Math, this )};
myArray = [1,2,3];

console.log( myArray.max() );
Izz
źródło
1
Okropnie nieefektywny.
Frank Schmitt
@FrankSchmitt, dziękuję, zgadzam się. Oryginalna odpowiedź nie była dobrym rozwiązaniem. Sortuj domyślnie nie sortuje liczb, traktuje elementy jak ciągi znaków. Zredagowałem moją odpowiedź, aby mieć odpowiedni rodzaj.
Izz
Nie o to mi chodziło. Sortowanie tablicy w celu znalezienia maksimum jest samo w sobie bardzo nieefektywne, ponieważ zajmuje co najmniej N log N operacji, podczas gdy znalezienie maksimum można wykonać w N operacjach.
Frank Schmitt
1

Możesz także użyć forEach :

var maximum = Number.MIN_SAFE_INTEGER;

var array = [-3, -2, 217, 9, -8, 46];
array.forEach(function(value){
  if(value > maximum) {
    maximum = value;
  }
});

console.log(maximum); // 217

Benny Neugebauer
źródło
1

Korzystanie - Array.prototype.reduce()jest fajne!

[267, 306, 108].reduce((acc,val)=> (acc>val)?acc:val)

gdzie acc = akumulator i val = aktualna wartość ;

var a = [267, 306, 108].reduce((acc,val)=> (acc>val)?acc:val);

console.log(a);

arora
źródło
1

Możesz spróbować

var arr = [267,306,108];
var largestNum = 0;
for(i=0;i<arr.length;i++) {
   if(arr[i]>largest){
    var largest = arr[i];
   }
}
console.log(largest);
Aasha Joney
źródło
1

Właśnie zacząłem od JS, ale myślę, że ta metoda byłaby dobra:

var array = [34, 23, 57, 983, 198];<br>
var score = 0;

for(var i = 0; i = array.length; i++) {
  if(array[ i ] > score) {
    score = array[i];
  }
}
Jakub Karki
źródło
Będzie to miało problem, jeśli arrayzawiera tylko liczby ujemne.
Teepeemm,
0

Znajdź największą liczbę w tablicy wielowymiarowej

var max = []; 

for(var i=0; arr.length>i; i++ ){

   var arra = arr[i];
   var largest = Math.max.apply(Math, arra);
   max.push(largest);

   }
return max;
Liveindream
źródło
Zawsze jest wskazane, aby dodać trochę skomplikowanego objaśnienia do swojego kodu, szczególnie jeśli istnieje już wiele innych odpowiedzi. Dlaczego ten jest inny / lepszy?
Bowdzone
@Bowdzone, dzięki za komentarz. ten sposób jest bardzo prosty, co ułatwia zrozumienie przy niewielkiej wiedzy na temat zaledwie kilku metod.
Liveindream,
To nie zwraca największej liczby, zwraca tablicę o największej liczbie każdej tablicy w tablicy wielowymiarowej. Trzeba by dodać np. var tmax = Math.max.apply(Math, max)Lub jeszcze lepiej użyć zamknięcia funkcji pętli np. W stackoverflow.com/a/54980012/7438857 . Dzięki tej modyfikacji, to lepiej odpowiedziało na osobnym pytaniu, w jaki sposób „Znajdź największą liczbę w tablicy wielowymiarowej” lub na stackoverflow.com/questions/32616910/... . WIP: jsfiddle.net/jamesray/3cLu9for/8 .
James Ray
stackoverflow.com/a/32617019/7438857 jest lepszą odpowiedzią na właściwe pytanie, podczas gdy ta odpowiedź nie odpowiada na powyższe pytanie, zwraca największą liczbę w każdej tablicy w tablicy wielowymiarowej.
James Ray
0

Uruchom to:

Array.prototype.max = function(){
    return Math.max.apply( Math, this );
};

A teraz spróbuj [3,10,2].max()wrócić10

RegarBoy
źródło
0

Znajdź wartość Max i Min za pomocą Bubble Sort

    var arr = [267, 306, 108];

    for(i=0, k=0; i<arr.length; i++) {
      for(j=0; j<i; j++) {
        if(arr[i]>arr[j]) {
          k = arr[i];
          arr[i] = arr[j];
          arr[j] = k;
        }
      }
    }
    console.log('largest Number: '+ arr[0]);
    console.log('Smallest Number: '+ arr[arr.length-1]);

Mano
źródło
1
(1) Tablice JavaScript mają już funkcję sortowania O (n log n). (2) Sortowanie bąbelkowe to O (n ^ 2). (3) Znalezienie min i maks to O (n).
Teepeemm,
0

Spróbuj tego

function largestNum(arr) {
  var currentLongest = arr[0]

  for (var i=0; i< arr.length; i++){
    if (arr[i] > currentLongest){
      currentLongest = arr[i]
    }
  }

  return currentLongest
}
Toufiq
źródło
1
Czy ta odpowiedź znacznie różni się od wielu innych na tej stronie?
Teepeemm,
0

Zgodnie z komentarzem @ Quasimondo , który wydaje się być w dużej mierze pominięty, poniższe wyniki wydają się mieć najlepszą wydajność, jak pokazano tutaj: https://jsperf.com/finding-maximum-element-in-an-array . Należy zauważyć, że chociaż dla tablicy w pytaniu wydajność może nie mieć znaczącego wpływu, w przypadku dużych tablic wydajność staje się ważniejsza, i ponownie, jak zauważono, użycie Math.max()nawet nie działa, jeśli długość tablicy jest większa niż 65535. Zobacz także tę odpowiedź .

function largestNum(arr) {
    var d = data;
    var m = d[d.length - 1];
    for (var i = d.length - 1; --i > -1;) {
      if (d[i] > m) m = d[i];
    }
    return m;
}
James Ray
źródło
0

Podejście rekurencyjne, jak to zrobić przy użyciu operatorów trójskładnikowych

const findMax = (arr, max, i) => arr.length === i ? max :
  findMax(arr, arr[i] > max ? arr[i] : max, ++i)

const arr = [5, 34, 2, 1, 6, 7, 9, 3];
const max = findMax(arr, arr[0], 0)
console.log(max);

Eugen Sunic
źródło
0

for/ofRozwiązanie z jedną pętlą:

const numbers = [2, 4, 6, 8, 80, 56, 10];


const findMax = (...numbers) => {
  let currentMax = numbers[0]; // 2

  for (const number of numbers) {
    if (number > currentMax) {
      console.log(number, currentMax);
      currentMax = number;
    }
  }
  console.log('Largest ', currentMax);
  return currentMax;
};

findMax(...numbers);

Mile Mijatović
źródło