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?


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.


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.


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


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)

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


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]

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

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

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 .


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

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

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;



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

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

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


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


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

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

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;

É 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


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


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
}

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

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


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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.