¿Cómo puedo encontrar el número más grande contenido en una matriz de JavaScript?

206

Tengo un simple objeto de matriz de JavaScript que contiene algunos números.

[267, 306, 108]

¿Hay una función que encuentre el número más grande en esta matriz?

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

Respuestas:

315

Resig al rescate:

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

Advertencia : dado que el número máximo de argumentos es tan bajo como 65535 en algunas máquinas virtuales , use un bucle for si no está seguro de que la matriz sea tan pequeña.

Creciente Fresco
fuente
15
¡Ah, pero ahora tiene la etiqueta de calidad SO pegada de una manera ligeramente torcida!
Shog9
2
FWIW, si el rendimiento es un factor en su solución, lo probaría en comparación con su propia función fácil de codificar para asegurarme de que funcione bien. Tendemos a suponer que la implementación nativa será más rápida; de hecho, el costo de la applyllamada puede eliminarlo muy fácilmente.
TJ Crowder
2
¿Qué sucede si la longitud de mi matriz es mayor que el límite de recuento de parámetros?
lukas.pukenis
3
@CrescentFresh de acuerdo con esto: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… está codificado en 65535. De acuerdo con esto: code.google.com/p/v8/issues/detail?id = 172 y por el conocimiento de que los argumentos se introducen en la pila, sabemos que no es ilimitado
lukas.pukenis
9
Además, este método no es robusto. Se produce un error si la matriz es mayor que el tamaño de la pila mamximum que resulta enRangeError: Maximum call stack size exceeded.
Marcos Lundin
197

Puede usar la función de aplicación para llamar a Math.max :

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

¿Cómo funciona?

El aplicar función de se usa para llamar a otra función, con un contexto y argumentos dados, proporcionados como una matriz. Las funciones min y max pueden tomar una cantidad arbitraria de argumentos de entrada: Math.max (val1, val2, ..., valN)

Entonces si llamamos:

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

La función de aplicación ejecutará:

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

Tenga en cuenta que el primer parámetro, el contexto, no es importante para estas funciones, ya que son estáticas, funcionarán independientemente de lo que se pase como contexto.

CMS
fuente
2
Whoa pones tus respuestas con mucho esfuerzo: D
ShrekOverflow
1
Eso es genial. Pero, ¿qué sucede si la longitud de mi matriz excede el límite de tamaño del parámetro (de la función)? Entonces que ?
lukas.pukenis
1
Me gusta esta respuesta mejor que las otras porque explica qué hace todo y por qué. +1
Marvin
59

La sintaxis más fácil, con el nuevo operador de propagación :

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

Fuente: Mozilla MDN

AI
fuente
2
Sin embargo, tanto spread (...) como apply fallarán o devolverán el resultado incorrecto si la matriz tiene demasiados elementos developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Green
@Green FWIW, el límite de recuento de parámetros es 65536 (al menos en Chrome) ([fuente ( bugs.webkit.org/show_bug.cgi?id=80797)] ). Entonces, si su matriz tiene más de 65536 elementos, esta respuesta no funcionará.
mgthomas99
44
65536 debería ser suficiente para cualquiera
vsync
41

No soy un experto en JS, pero quería ver cómo se comparan estos métodos, así que esta fue una buena práctica para mí. No sé si esta es técnicamente la forma correcta de probar estos, pero simplemente los ejecuté uno tras otro, como puede ver en mi código.

Ordenar y obtener el valor 0 es, con mucho, el peor método (y modifica el orden de su matriz, lo que puede no ser deseable). Para los demás, la diferencia es insignificante a menos que esté hablando de millones de índices.

Resultados promedio de cinco ejecuciones con una matriz de números aleatorios de 100,000 índices:

  • reducir tomó 4.0392 ms para ejecutarse
  • Math.max.apply tardó 3.3742 ms en ejecutarse
  • ordenar y obtener el valor 0 tardó 67.4724 ms en ejecutarse
  • Math.max dentro de reduce () tardó 6.5804ms en ejecutarse
  • La función findmax personalizada tardó 1.6102ms en ejecutarse

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
fuente
77
Para mí, esta es la mejor respuesta para esta pregunta.
rzelek
1
He hecho jsperf testslo anterior
vsync
37

Descubrí que para matrices más grandes (~ 100k elementos), en realidad vale la pena simplemente iterar la matriz con un forbucle humilde , con un rendimiento ~ 30% mejor 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 referencia

Jack
fuente
3
FWIW, sale al 84% ahora en Chrome 31.
Ilan Biala
31

Puede ordenar la matriz en orden descendente y obtener el primer elemento:

[267, 306, 108].sort(function(a,b){return b-a;})[0]
Gumbo
fuente
44
Supongo que también podría ordenar y obtener el último elemento ...?
Shog9
@ Shog9: Sí, pero necesitaría especificar la función de comparación por su cuenta:sort(function(a,b){return b-a;})
Gumbo el
9
Ah Estaba pensando más como:[...].sort().pop()
Shog9
44
"encontrar el número toma orden-n, ordenar toma entre orden (n log n) a orden (n al cuadrado), dependiendo del algoritmo de clasificación utilizado" - webmasterworld.com/forum91/382.htm
Marco Luglio
2
También tenga en cuenta que esto ordena la matriz, que puede o no ser un efecto secundario deseado. La solución de aplicación tiene mejor rendimiento y no tiene efectos secundarios.
Caleb
28

Qué tal esto:

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

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

console.log(largest);
brroshan
fuente
Si hubiera visto esta respuesta primero (actualmente al final de la lista) habría ahorrado dos horas.
user139301
1
El enfoque Math.max es probablemente el más estándar, pero recibía un desbordamiento de la pila cuando la matriz era demasiado grande (500K). Esta respuesta es rápida y eficiente y es la que terminé usando yo mismo, así que estoy votando esta.
Jay
8

¿ Qué tal usar Array.reduce ?

[0,1,2,3,4].reduce(function(previousValue, currentValue){
  return Math.max(previousValue,currentValue);
});
CodeToad
fuente
El valor inicial debe establecerse en -Infinity.
Ja͢ck
@ Jack, ¿por qué es necesario? Incluso con una matriz de todos los números negativos, obtengo un resultado válido.
CodeToad
1
Es el caso límite por el cual la matriz está vacía.
Ja͢ck
5

Casi todas las respuestas usan lo Math.max.apply()que es agradable y elegante pero tiene limitaciones.

Los argumentos de la función se colocan en la pila que tiene una desventaja: un límite. Entonces, si su matriz es más grande que el límite, fallará conRangeError: Maximum call stack size exceeded.

Para encontrar un tamaño de pila de llamadas, utilicé 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;
  }
}

Resultó ser el más grande en FireFox en mi máquina: 591519 . Esto significa que si su matriz contiene más de 591519 elementos, Math.max.apply()dará como resultado RangeError .

La mejor solución para este problema es la forma 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];
}

He escrito sobre esta pregunta en mi blog aquí .

lukas.pukenis
fuente
1
Esto no es justo. Quiero la respuesta aquí, en SO, no otro enlace a otro recurso de terceros. Especialmente cuando se combina con "todo aquí es malo, pero ve, mira, es genial en mi blog ..."
osa
@SergeyOrshanskiy un enlace a un tercero funciona muy bien en caso de que se actualice con nuevas perspectivas y soluciones. Además, no hay necesidad de sentirse ofendido. La gente solo quiere resolver tus problemas también. Yo también quería resolverlo, así que escribí sobre eso en mi blog
lukas.pukenis el
5

Encontrar el valor máximo y mínimo de manera fácil y manual. Este código es mucho más rápido que Math.max.apply; He intentado hasta 1000k números en 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
fuente
findmax()da el resultado incorrecto si solo hay números negativos en la matriz; findmin()da el resultado incorrecto para una matriz vacía.
Ja͢ck
3

Sí, por supuesto, existe: Math.max.apply(null,[23,45,67,-45]) y el resultado vuelve 67;

usuario3702000
fuente
3

Un trazador de líneas simple

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

No hay que olvidar que la envoltura se puede hacer con Function.prototype.bind, que le da un "todo-nativa" función .

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

También puede extender Arraypara tener esta función y hacerla parte de cada matriz.

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

console.log( myArray.max() );
Izz
fuente
1
Terriblemente ineficiente.
Frank Schmitt
@ FrankSchmitt, gracias, estoy de acuerdo. La respuesta original no fue una buena solución. Ordenar por defecto no ordena los números, trata los elementos como cadenas. Edité mi respuesta para tener el tipo correcto.
Izz
Ese no era mi punto. Ordenar una matriz para encontrar el máximo es per se terriblemente ineficiente, ya que requiere al menos N log N operaciones, mientras que encontrar el máximo se puede hacer en N operaciones.
Frank Schmitt
1

También puedes usar 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
fuente
1

¡Usar Array.prototype.reduce()es genial!

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

donde acc = acumulador y val = valor actual ;

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

console.log(a);

arora
fuente
1

Puedes probar esto,

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

Acabo de comenzar con JS pero creo que este método sería bueno:

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
fuente
Esto tendrá problemas si arraysolo contiene números negativos.
Teepeemm
0

Encuentra el número más grande en una 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
fuente
Siempre es aconsejable agregar alguna explicación elaborada a su código, especialmente si ya hay muchas otras respuestas. ¿Por qué es este diferente / mejor?
Bowdzone
@Bowdzone, gracias por el comentario. de esta manera es muy básico lo que lo hace fácil de entender con un poco de conocimiento de solo unos pocos métodos.
Liveindream
Esto no devuelve el número más grande, devuelve una matriz del mayor número de cada matriz en la matriz multidimensional. Debería agregar var tmax = Math.max.apply(Math, max), por ejemplo , o mejor aún, usar el cierre de una función de bucle, por ejemplo, en stackoverflow.com/a/54980012/7438857 . Con esta modificación, es mejor responder a una pregunta por separado, ¿cómo "encuentra el número más grande en una matriz multidimensional", o en stackoverflow.com/questions/32616910/… . WIP: jsfiddle.net/jamesray/3cLu9for/8 .
James Ray
stackoverflow.com/a/32617019/7438857 es una mejor respuesta a la pregunta correcta, aunque esta respuesta no responde a la pregunta anterior, devuelve el número más grande en cada matriz dentro de una matriz multidimensional.
James Ray
0

Ejecuta esto:

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

Y ahora intenta [3,10,2].max()devoluciones10

RegarBoy
fuente
0

Encuentre el valor máximo y mínimo con el método de burbuja

    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
fuente
1
(1) Las matrices Javascript ya tienen una función de clasificación O (n log n). (2) El tipo de burbuja es O (n ^ 2). (3) Encontrar el mínimo y el máximo es O (n).
Teepeemm
0

Prueba esto

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
fuente
1
¿Es esta respuesta sustancialmente diferente de muchas de las otras en esta página?
Teepeemm
0

Según el comentario de @ Quasimondo , que parece haberse perdido en gran medida, el siguiente parece tener el mejor rendimiento como se muestra aquí: https://jsperf.com/finding-maximum-element-in-an-array . Tenga en cuenta que, aunque para el conjunto de la pregunta, el rendimiento puede no tener un efecto significativo, para el rendimiento de conjuntos grandes se vuelve más importante, y nuevamente, como se señaló, el uso Math.max()ni siquiera funciona si la longitud del conjunto es superior a 65535. Consulte también esta respuesta .

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

Un enfoque recursivo sobre cómo hacerlo utilizando operadores ternarios

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

for/ofSolución de un bucle:

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