Como posso encontrar o maior número contido em uma matriz JavaScript?

206

Eu tenho um simples objeto JavaScript Array que contém alguns números.

[267, 306, 108]

Existe uma função que encontre o maior número nessa matriz?

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

Respostas:

315

Resig para o resgate:

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

Aviso : como o número máximo de argumentos é tão baixo quanto 65535 em algumas VMs , use um loop for se não tiver certeza de que a matriz é tão pequena.

Crescent Fresh
fonte
15
Ah, mas agora ele tem o adesivo de qualidade SO afixado de uma maneira um pouco torta!
Shog9
2
FWIW, se o desempenho é um fator em sua solução, eu testaria isso em comparação à sua própria função facilmente codificada para garantir que ela tenha um bom desempenho. Tendemos a supor que a implementação nativa será mais rápida; de fato, o custo da applyligação pode eliminar isso com muita facilidade.
TJ Crowder
2
E se o tamanho da minha matriz for maior que o limite de contagem de parâmetros?
Lukas.pukenis
3
@CrescentFresh de acordo com isso: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… está codificado para 65535. De acordo com isso: code.google.com/p/v8/issues/detail?id = 172 e pelo conhecimento que os argumentos são empurrados na pilha sabemos que não é ilimitado
lukas.pukenis
9
Além disso, esse método não é robusto. Ele falha se a matriz é maior do que o tamanho da pilha mamximum resultando emRangeError: Maximum call stack size exceeded.
Mark Lundin
197

Você pode usar a função aplicar, para chamar Math.max :

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

Como funciona?

A função apply é usada para chamar outra função, com um determinado contexto e argumentos, fornecidos como uma matriz. As funções min e max podem receber um número arbitrário de argumentos de entrada: Math.max (val1, val2, ..., valN)

Então, se chamarmos:

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

A função aplicar irá executar:

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

Observe que o primeiro parâmetro, o contexto, não é importante para essas funções, pois são estáticas; elas funcionarão independentemente do que é passado como contexto.

CMS
fonte
2
Whoa, você coloca suas respostas com muito esforço: D
ShrekOverflow
1
Isso é ótimo. Mas e se o comprimento da minha matriz exceder o limite de tamanho do parâmetro (da função)? O que então?
Lukas.pukenis
1
Gosto mais dessa resposta do que as outras, porque explica o que tudo faz e por que. +1
Marvin
59

A sintaxe mais fácil, com o novo operador de propagação :

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

Fonte: Mozilla MDN

AI
fonte
2
No entanto, a propagação (...) e a aplicação falharão ou retornarão o resultado errado se a matriz tiver muitos elementos developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Green
@ Green FWIW, o limite de contagem de parâmetros é 65536 (pelo menos no Chrome) ([fonte ( bugs.webkit.org/show_bug.cgi?id=80797)] ). Portanto, se sua matriz tiver mais de 65536 elementos, esta resposta não funcionará.
mgthomas99
4
65536 deve ser suficiente para qualquer um
vsync
41

Não sou especialista em JS, mas queria ver como esses métodos se compilam, portanto, isso foi uma boa prática para mim. Não sei se é tecnicamente o caminho certo para testar esses desempenhos, mas apenas os executei um após o outro, como você pode ver no meu código.

Classificar e obter o valor 0 é de longe o pior método (e modifica a ordem da sua matriz, o que pode não ser desejável). Para os outros, a diferença é insignificante, a menos que você esteja falando de milhões de índices.

Resultados médios de cinco execuções com uma matriz de 100.000 índices de números aleatórios:

  • reduzir levou 4.0392ms para executar
  • Math.max.apply levou 3.3742ms para executar
  • classificar e obter o 0º valor levou 67,4724ms para ser executado
  • Math.max dentro de replace () levou 6.5804ms para executar
  • A função findmax personalizada levou 1.6102ms para executar

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
fonte
7
Para mim, esta é a melhor resposta para esta pergunta.
rzelek
1
Eu fiz jsperf testspara o acima exposto
vsync
37

Descobri que para matrizes maiores (~ 100k elementos), na verdade vale a pena simplesmente iterar a matriz com um forloop humilde , com desempenho ~ 30% melhor que 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;
}

Resultados de referência

Ja͢ck
fonte
3
FWIW, chega a 84% agora no Chrome 31.
Ilan Biala
31

Você pode classificar a matriz em ordem decrescente e obter o primeiro item:

[267, 306, 108].sort(function(a,b){return b-a;})[0]
quiabo
fonte
4
Eu diria que você também pode classificar e obter o último item ...?
Shog9
@ Shog9: Sim, mas você precisaria especificar a função de comparação por conta própria:sort(function(a,b){return b-a;})
Gumbo
9
Ah Eu estava pensando mais como:[...].sort().pop()
Shog9 04/09/09
4
"encontrar o número leva a ordem n, a classificação leva entre ordem (n log n) a ordem (n ao quadrado), depende do algoritmo de classificação usado" - webmasterworld.com/forum91/382.htm
Marco Luglio
2
Lembre-se também de que isso classifica a matriz, o que pode ou não ser o efeito colateral desejado. A solução de aplicação tem melhor desempenho e não tem efeitos colaterais.
Caleb
28

Que tal agora:

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

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

console.log(largest);
brroshan
fonte
Se eu tivesse visto essa resposta primeiro (atualmente no final da lista), teria economizado duas horas.
User139301
1
A abordagem Math.max é provavelmente a mais padrão, mas eu estava obtendo um estouro de pilha quando a matriz era muito grande (500K). Essa resposta é rápida e eficiente e foi a que acabei usando, então estou votando nessa.
Jay
8

Que tal usar Array.reduce ?

[0,1,2,3,4].reduce(function(previousValue, currentValue){
  return Math.max(previousValue,currentValue);
});
CodeToad
fonte
O valor inicial deve ser definido como -Infinity.
Ja Sepck 25/09/14
@ Jack, por que isso é necessário? mesmo com uma matriz de todos os números negativos, recebo um resultado válido.
CodeToad
1
É o caso em que a matriz está vazia.
Ja Sepck
5

Quase todas as respostas usam o Math.max.apply()que é bom e elegante, mas tem limitações.

Os argumentos da função são colocados na pilha que tem uma desvantagem - um limite. Portanto, se sua matriz for maior que o limite, ela falhará comRangeError: Maximum call stack size exceeded.

Para encontrar um tamanho de pilha de chamadas, usei este código:

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

Ele provou ser o maior no FireFox na minha máquina - 591519 . Isso significa que, se sua matriz contiver mais de 591519 itens, Math.max.apply()resultará em RangeError .

A melhor solução para esse problema é a maneira iterativa (crédito: 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];
}

Eu escrevi sobre esta questão no meu blog aqui .

lukas.pukenis
fonte
1
Isto não é justo. Quero a resposta aqui, no SO, não outro link para outro recurso de terceiros. Especialmente quando ele é combinado com "tudo aqui é ruim, mas vai, olhar, é tão grande no meu blog ..."
osa
@SergeyOrshanskiy um link para terceiros funciona muito bem caso seja atualizado com novas informações e soluções. Também não há necessidade de se sentir ofendido. As pessoas só querem resolver seus problemas também. Eu também queria resolvê-lo, então escrevi sobre isso no meu blog
lukas.pukenis 15/10
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
fonte
2
No entanto, a propagação (...) e a aplicação falharão ou retornarão o resultado errado se a matriz tiver muitos elementos developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Green
5

Encontrar o valor máximo e mínimo da maneira fácil e manual. Este código é muito mais rápido que Math.max.apply; Eu tentei até 1000k números na matriz.

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
fonte
findmax()fornece o resultado errado se houver apenas números negativos na matriz; findmin()fornece o resultado errado para uma matriz vazia.
Ja͢ck 25/09
3

Sim, é claro que existe: Math.max.apply(null,[23,45,67,-45]) e o resultado retorna 67;

user3702000
fonte
3

Forro simples

[].sort().pop()
YasirAzgar
fonte
1

Não se esqueça que o envoltório pode ser feito com Function.prototype.bind, dando-lhe um "tudo-nativo" função .

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

Você também pode estender Arraypara ter essa função e torná-la parte de cada matriz.

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

console.log( myArray.max() );
Izz
fonte
1
Terrivelmente ineficiente.
26514 Frank Schmitt
@FrankSchmitt, obrigado, eu concordo. A resposta original não foi uma boa solução. Classificar por padrão não classifica números, trata elementos como strings. Editou minha resposta para ter a classificação correta.
Izz
Esse não era o meu ponto. Classificar uma matriz para encontrar o máximo é, por si só, terrivelmente ineficiente, uma vez que são necessárias pelo menos N operações de log N, enquanto que encontrar o máximo pode ser feito em N operações.
24714 Frank Schmitt
1

Você também pode usar o 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
fonte
1

Usando - Array.prototype.reduce()é legal!

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

onde acc = acumulador e val = valor atual ;

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

console.log(a);

arora
fonte
1

Você pode tentar isso,

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
fonte
1

Comecei com JS, mas acho que esse método seria bom:

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
fonte
Isso terá problemas se arraycontiver apenas números negativos.
Teepeemm
0

Encontre o maior número em uma matriz multidimensional

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
fonte
É sempre aconselhável adicionar alguma explicação elaborada ao seu código, especialmente se já houver várias outras respostas. Por que este é diferente / melhor?
Bowdzone
@ Bowdzone, obrigado pelo comentário. dessa maneira, é muito básico o que facilita a compreensão com um pouco de conhecimento de apenas alguns métodos.
Liveindream 12/08/15
Isso não retorna o maior número, ele retorna uma matriz do maior número de cada matriz na matriz multidimensional. Você precisaria adicionar var tmax = Math.max.apply(Math, max), por exemplo , ou melhor ainda, usar o fechamento de uma função de loop, por exemplo, em stackoverflow.com/a/54980012/7438857 . Com essa modificação, é melhor responder a uma pergunta separada, como você "encontra o maior número em uma matriz multidimensional" ou em stackoverflow.com/questions/32616910/… . WIP: jsfiddle.net/jamesray/3cLu9for/8 .
James Ray
stackoverflow.com/a/32617019/7438857 é uma resposta melhor para a pergunta certa, embora essa resposta não responda à pergunta acima, ela retorna o maior número em cada matriz em uma matriz multidimensional.
James Ray
0

Rode isto:

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

E agora tente [3,10,2].max()retornos10

RegarBoy
fonte
0

Encontre o valor máximo e mínimo usando a classificação de bolha

    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
fonte
1
(1) As matrizes Javascript já possuem uma função de classificação O (n log n). (2) A classificação das bolhas é O (n ^ 2). (3) Encontrar o mínimo e o máximo é O (n).
Teepeemm
0

Tente isto

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
fonte
1
Essa resposta é substancialmente diferente de muitas outras nesta página?
Teepeemm
0

Conforme o comentário de @ Quasimondo , que parece ter sido amplamente esquecido, o abaixo parece ter o melhor desempenho, como mostrado aqui: https://jsperf.com/finding-maximum-element-in-an-array . Observe que, para a matriz em questão, o desempenho pode não ter um efeito significativo, para matrizes grandes o desempenho se torna mais importante e, novamente, conforme observado, o uso Math.max()nem funciona se o comprimento da matriz for superior a 65535. Consulte também esta resposta .

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
fonte
0

Uma abordagem recursiva sobre como fazê-lo usando operadores ternários

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
fonte
0

for/ofSolução de um loop:

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ć
fonte