Come posso trovare il numero più grande contenuto in un array JavaScript?


206

Ho un semplice oggetto Array JavaScript contenente alcuni numeri.

[267, 306, 108]

Esiste una funzione che trova il numero più grande in questo array?


22
Math.max(...[267, 306, 108]);
Jacksonkr,

Risposte:


315

Resig in soccorso:

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

Avviso : poiché il numero massimo di argomenti è inferiore a 65535 su alcune VM , utilizzare un ciclo for se non si è certi che l'array sia così piccolo.


15
Ah, ma ora ha l' adesivo SO di qualità apposto in un modo solo leggermente storto!
Shog9

2
FWIW, se le prestazioni sono un fattore nella tua soluzione, lo testerei rispetto alla tua funzione facilmente codificabile per assicurarmi che funzioni bene. Tendiamo a supporre che l'implementazione nativa sarà più veloce; in effetti, il costo della applychiamata può eliminarlo molto facilmente.
TJ Crowder,

2
Cosa succede se la lunghezza della mia matrice è maggiore del limite di conteggio dei parametri?
lukas.pukenis,

3
@CrescentFresh secondo questo: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… è hardcoded a 65535. Secondo questo: code.google.com/p/v8/issues/detail?id = 172 e sapendo che gli argomenti vengono
inseriti

9
Inoltre, questo metodo non è robusto. Non riesce se l'array è più grande della dimensione massima dello stack risultanteRangeError: Maximum call stack size exceeded.
Mark Lundin

197

Puoi usare la funzione apply, per chiamare Math.max :

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

Come funziona?

il applicano funzione viene utilizzata per chiamare un'altra funzione, con un determinato contesto e argomenti, fornita come matrice. Le funzioni min e max possono accettare un numero arbitrario di argomenti di input: Math.max (val1, val2, ..., valN)

Quindi se chiamiamo:

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

La funzione di applicazione eseguirà:

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

Si noti che il primo parametro, il contesto, non è importante per queste funzioni poiché sono statici, funzioneranno indipendentemente da ciò che viene passato come contesto.


2
Whoa hai dato le tue risposte con molto sforzo: D
ShrekOverflow,

1
È fantastico. Ma cosa succede se la lunghezza della mia matrice supera il limite della dimensione del parametro (della funzione)? Cosa poi ?
lukas.pukenis,

1
Mi piace questa risposta meglio delle altre perché spiega cosa fa tutto e perché. +1
Marvin,

59

La sintassi più semplice, con il nuovo operatore di diffusione :

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

Fonte: Mozilla MDN


2
Tuttavia, sia spread (...) che apply falliranno o restituiranno il risultato sbagliato se l'array ha troppi elementi developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Green

@Green FWIW, il limite di conteggio dei parametri è 65536 (almeno su Chrome) ([fonte ( bugs.webkit.org/show_bug.cgi?id=80797)] ). Quindi, se l'array ha più di 65536 elementi, questa risposta non funzionerà.
mgthomas99

4
65536 dovrebbe essere abbastanza per chiunque
vsync

41

Non sono un esperto di JS, ma volevo vedere come si combinano questi metodi, quindi questa è stata una buona pratica per me. Non so se questo è tecnicamente il modo giusto per testarli, ma li ho eseguiti uno dopo l'altro, come puoi vedere nel mio codice.

Ordinare e ottenere il valore 0 è di gran lunga il metodo peggiore (e modifica l'ordine dell'array, che potrebbe non essere desiderabile). Per gli altri, la differenza è trascurabile a meno che non si stiano parlando di milioni di indici.

Risultati medi di cinque esecuzioni con un array di 100.000 indici di numeri casuali:

  • ridurre ha richiesto 4.0392ms per l'esecuzione
  • Math.max.apply ha impiegato 3.3742ms per l'esecuzione
  • l'ordinamento e l'ottenimento del valore 0 hanno richiesto 67,4724 ms per l'esecuzione
  • Math.max in riduce () ha impiegato 6.5804ms per funzionare
  • personalizzato funzione FindMax preso 1.6102ms a correre

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)

7
Per me, questa è la risposta migliore per questa domanda.
rzelek,

1
Ho fatto jsperf testsquanto sopra
vsync il

37

Ho scoperto che per array più grandi (~ 100k elementi), in realtà paga semplicemente iterare l'array con un forciclo umile , con prestazioni ~ 30% migliori di 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;
}

Risultati benchmark


3
FWIW, esce all'84% ora su Chrome 31.
Ilan Biala,

31

È possibile ordinare l'array in ordine decrescente e ottenere il primo elemento:

[267, 306, 108].sort(function(a,b){return b-a;})[0]

4
Suppongo che potresti anche ordinare e ottenere l'ultimo elemento ...?
Shog9

@ Shog9: Sì, ma dovresti specificare la funzione di confronto da solo:sort(function(a,b){return b-a;})
Gumbo

9
Ah. Stavo pensando più come:[...].sort().pop()
Shog9

4
"trovare il numero richiede order-n, l'ordinamento richiede tra order (n log n) per ordinare (n quadrati), dipende dall'algoritmo di ordinamento utilizzato" - webmasterworld.com/forum91/382.htm
Marco Luglio,

2
Inoltre, tieni presente che questo ordina l'array, che può essere o meno un effetto collaterale desiderato. La soluzione di applicazione ha prestazioni migliori e non ha effetti collaterali.
Caleb,

28

Cosa ne pensi di questo:

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

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

console.log(largest);

Se avessi visto prima questa risposta (attualmente in fondo all'elenco) avrei risparmiato due ore.
user139301,

1
L'approccio Math.max è probabilmente il più standard, ma stavo ottenendo un overflow dello stack quando l'array era troppo grande (500 KB). Questa risposta è veloce ed efficiente ed è quella che ho finito per usare me stesso, quindi sto votando questo.
Jay,

8

che ne dici di usare Array.reduce ?

[0,1,2,3,4].reduce(function(previousValue, currentValue){
  return Math.max(previousValue,currentValue);
});

Il valore iniziale deve essere impostato su -Infinity.
Ja͢ck,

@ Jack, perché è necessario? anche con una matrice di tutti i numeri negativi, ottengo un risultato valido.
CodeToad,

1
È il caso limite in cui l'array è vuoto.
Ja͢ck,

5

Quasi tutte le risposte usano Math.max.apply()che è bello e dandy ma ha dei limiti.

Gli argomenti delle funzioni sono collocati nello stack che ha un aspetto negativo: un limite. Quindi, se il tuo array è più grande del limite, falliràRangeError: Maximum call stack size exceeded.

Per trovare una dimensione dello stack di chiamate ho usato questo codice:

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;
  }
}

Si è rivelato il più grande su FireFox sulla mia macchina - 591519 . Ciò significa che se l'array contiene più di 591519 elementi, si Math.max.apply()otterrà RangeError .

La migliore soluzione per questo problema è il modo iterativo (credito: 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];
}

Ho scritto di questa domanda sul mio blog qui .


1
Non è giusto. Voglio la risposta proprio qui, su SO, non un altro link a un'altra risorsa di terze parti. Soprattutto quando combinato con "tutto qui è male, ma vai, guarda, è così bello sul mio blog ..."
osa,

@SergeyOrshanskiy un collegamento a una terza parte funziona molto bene nel caso in cui venga aggiornato con nuove insigths e soluzioni. Inoltre, non è necessario sentirsi offesi. Le persone vogliono solo risolvere anche i tuoi problemi. Volevo risolverlo anch'io, quindi ne ho scritto sul mio blog
lukas.pukenis,


5

Trovare il valore massimo e minimo in modo semplice e manuale. Questo codice è molto più veloce di Math.max.apply; Ho provato fino a 1000k numeri in array.

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;
}

findmax()dà il risultato sbagliato se ci sono solo numeri negativi nell'array; findmin()dà il risultato sbagliato per un array vuoto.
Ja͢ck,


3

Sì certo esiste: Math.max.apply(null,[23,45,67,-45]) e il risultato ritorna 67;



1

Non dimenticate che l'involucro può essere fatto con Function.prototype.bind, dando un "all-native" la funzione .

var aMax = Math.max.apply.bind(Math.max, Math);
aMax([1, 2, 3, 4, 5]); // 5

1

È inoltre possibile estendere Arrayquesta funzione e renderla parte di ogni array.

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

console.log( myArray.max() );

1
Terribilmente inefficiente.
Frank Schmitt,

@FrankSchmitt, grazie, sono d'accordo. La risposta originale non era una buona soluzione. Ordina per impostazione predefinita non ordina i numeri, tratta gli elementi come stringhe. Modificato la mia risposta per avere il giusto tipo.
Izz,

Non era quello il mio punto. L'ordinamento di un array per trovare il massimo è di per sé terribilmente inefficiente, poiché richiede almeno N operazioni N log, mentre la ricerca del massimo può essere eseguita in N operazioni.
Frank Schmitt,

1

Puoi anche usare per ogni :

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


1

Utilizzando - Array.prototype.reduce()è bello!

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

dove acc = accumulatore e val = valore corrente ;

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

console.log(a);


1

Puoi provare questo,

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);

1

Ho appena iniziato con JS ma penso che questo metodo sarebbe buono:

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];
  }
}

Ciò avrà problemi se arraycontiene solo numeri negativi.
Teepeemm,

0

Trova il numero più grande in un array multidimensionale

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;

È sempre consigliabile aggiungere una spiegazione elaborata al codice, soprattutto se ci sono già più altre risposte. Perché questo è diverso / migliore?
Bowdzone,

@Bowdzone, grazie per il commento. in questo modo è molto semplice ciò che rende semplice da capire con una piccola conoscenza di pochi metodi.
Liveindream,

Questo non restituisce il numero più grande, ma restituisce una matrice del numero più grande di ogni matrice nella matrice multidimensionale. Dovresti aggiungere ad esempio var tmax = Math.max.apply(Math, max), o meglio ancora, utilizzare una chiusura di una funzione di loop, ad esempio in stackoverflow.com/a/54980012/7438857 . Con questa modifica, è meglio rispondere a una domanda separata, come "trovare il numero più grande in un array multidimensionale" o su stackoverflow.com/questions/32616910/… . WIP: jsfiddle.net/jamesray/3cLu9for/8 .
James Ray

stackoverflow.com/a/32617019/7438857 è una risposta migliore alla domanda giusta, mentre questa risposta non risponde alla domanda precedente, restituisce il numero più grande in ciascun array all'interno di un array multidimensionale.
James Ray

0

Esegui questo:

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

E ora prova i [3,10,2].max()ritorni10


0

Trova il valore massimo e minimo usando 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]);


1
(1) Le matrici Javascript hanno già una funzione di ordinamento O (n log n). (2) L'ordinamento delle bolle è O (n ^ 2). (3) Trovare min e max è O (n).
Teepeemm,

0

Prova questo

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

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

  return currentLongest
}

1
Questa risposta è sostanzialmente diversa da molte delle altre in questa pagina?
Teepeemm,

0

Secondo il commento di @ Quasimondo , che sembra essere stato ampiamente perso, il seguito sembra avere le migliori prestazioni come mostrato qui: https://jsperf.com/finding-ma maximum-element-in-an-array . Si noti che mentre per l'array nella domanda, le prestazioni potrebbero non avere un effetto significativo, per gli array di grandi dimensioni le prestazioni diventano più importanti e, come notato, l' uso Math.max()non funziona nemmeno se la lunghezza dell'array è superiore a 65535. Vedere anche questa risposta .

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;
}

0

Un approccio ricorsivo su come farlo utilizzando operatori ternari

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);


0

Una for/ofsoluzione ad anello:

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);

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.