¿Cómo puedo obtener fácilmente el elemento min o max de una matriz de JavaScript?
Psuedocódigo de ejemplo:
let array = [100, 0, 50]
array.min() //=> 0
array.max() //=> 100
javascript
HankH
fuente
fuente
...
) conMath.max()
la siguiente manera:Math.max(...[2, 5, 16, 1])
. Vea mi respuesta hecha de la documentación de MDN .Math.max.apply(null, [2,5,16,1])
Respuestas:
¿Qué tal aumentar el objeto Array incorporado para usar
Math.max
/ en suMath.min
lugar:Aquí hay un JSFiddle .
Aumentar los muebles empotrados puede causar colisiones con otras bibliotecas (algunos ven), por lo que puede ser más cómodo con sólo
apply
'ingMath.xxx()
a la matriz directamente:Alternativamente, suponiendo que su navegador sea compatible con ECMAScript 6, puede usar el operador de propagación que funciona de manera similar al
apply
método:fuente
null
oMath
o{}
lo que seaapply()
ocall()
no tiene relación con el resultado.Math.max
no hace ni debe hacer referenciathis
internamente.Math.max.apply(null, $.makeArray(array));
.max
o un.min
método en el futuro. Escenario perfectamente realista: utiliza esta respuesta. En 2016, las especificaciones ES7 o ES8Array.max
yArray.min
. A diferencia de esta versión, trabajan en cadenas. Su futuro colega intenta obtener la secuencia alfabéticamente más reciente en una matriz con el.max()
método nativo ahora bien documentado , pero lo consigue misteriosamenteNaN
. Horas después, encuentra este código, ejecuta ungit blame
y maldice su nombre.Para una discusión completa ver: http://aaroncrane.co.uk/2008/11/javascript_max_api/
fuente
Math.max.apply(Math, array)
yMath.max.apply(null, array)
? El blog dice "... también tienes que repetir de forma redundante quemax
pertenece aMath
...", pero parece que no tengo que hacerlo (estableciendo el primer argumento deapply
asnull
).Math.max(a,b)
,Math
se pasa como elthis
valor, por lo que puede tener sentido hacer lo mismo al llamar conapply
. PeroMath.max
no utiliza elthis
valor, por lo que puede pasar el valor que desee.Para grandes matrices (~ 10⁷ elementos),
Math.min
yMath.max
ambas producen el siguiente error en Node.js.Una solución más robusta es no agregar todos los elementos a la pila de llamadas, sino pasar una matriz:
Si le preocupa la velocidad, el siguiente código es ~ 3 veces más rápido
Math.max.apply
que en mi computadora. Ver http://jsperf.com/min-and-max-in-array/2 .Si sus matrices contienen cadenas en lugar de números, también debe convertirlas en números. El siguiente código hace eso, pero ralentiza el código ~ 10 veces en mi máquina. Ver http://jsperf.com/min-and-max-in-array/3 .
fuente
min
ymax
al último elemento y reducir las iteraciones en 1 (while(--len)
);)very different results
lo hiciste 5 años después)reduce
solución es la más lenta. Incluso si trabaja con una matriz que tiene millones de elementos, es mejor usar el estándar for loop . Vea mi respuesta para más.Uso del operador de propagación (ES6)
Mostrar fragmento de código
fuente
If no arguments are given, the result is -∞.
tl; dr
Solución MDN
Los documentos oficiales de MDN
Math.max()
ya cubren este tema:Tamaño máximo de una matriz
De acuerdo con MDN, las
apply
soluciones extendidas tenían una limitación de 65536 que provenía del límite del número máximo de argumentos:Incluso proporcionan una solución híbrida que realmente no tiene un buen rendimiento en comparación con otras soluciones. Consulte la prueba de rendimiento a continuación para obtener más información.
En 2019, el límite real es el tamaño máximo de la pila de llamadas . Para los navegadores de escritorio modernos basados en Chromium, esto significa que cuando se trata de encontrar min / max con
apply
o spread, prácticamente el tamaño máximo para matrices de números solamente es ~ 120000 . Por encima de esto, habrá un desbordamiento de pila y se lanzará el siguiente error:Con el siguiente script (basado en esta publicación de blog ), al detectar ese error puede calcular el límite para su entorno específico.
¡Advertencia! ¡Ejecutar este script lleva tiempo y, dependiendo del rendimiento de su sistema, puede ralentizar o bloquear su navegador / sistema!
Rendimiento en matrices grandes
Basado en la prueba en el comentario de EscapeNetscape , creé algunos puntos de referencia que prueban 5 métodos diferentes en una matriz de solo números aleatorios con 100000 elementos .
En 2019, los resultados muestran que el bucle estándar (que por cierto no tiene la limitación de tamaño) es el más rápido en todas partes.
apply
y la propagación viene de cerca, luego mucho más tarde la solución híbrida de MDN y luegoreduce
como la más lenta.Casi todas las pruebas dieron los mismos resultados, excepto una en la que la propagación resultó ser la más lenta.
Si intensifica su matriz para tener 1 millón de elementos, las cosas comienzan a romperse y queda con el bucle estándar como una solución rápida y
reduce
más lenta.Punto de referencia JSPerf
Punto de referencia JSBen
Punto de referencia JSBench.me
Código fuente de referencia
Mostrar fragmento de código
fuente
Math.max.apply(Math, arr)
para una compatibilidad 'máxima'.(...)
yapply
fallarán o devolverán el resultado incorrecto si la matriz tiene demasiados elementos [...] La solución de reducción no tiene este problema" Al probar Chrome, FF, Edge e IE11 parece que es ok para una matriz de hasta 100k valores. (Probado en Win10 y los últimos navegadores: Chrome 110k, Firefox 300k, Edge 400k, IE11 150k).Si eres paranoico como yo sobre el uso
Math.max.apply
(lo que podría causar errores cuando se le dan matrices grandes de acuerdo con MDN ), intente esto:O, en ES6:
Desafortunadamente, las funciones anónimas son necesarias (en lugar de usar
Math.max.bind(Math)
porquereduce
no solo pasana
yb
a su función, sino tambiéni
y una referencia a la matriz en sí, por lo que debemos asegurarnos de no tratar de invocarlasmax
también.fuente
Math.max(...array)
?apply
, por lo tanto, tiene los mismos inconvenientes (límite máximo de argumentos).function arrayMax(array) { return array.reduce(function(a, b) { return Math.max(a, b); }); // <--------- missing ) }
Math.min()
sin valores, devuelveInfinity
, por lo que estas funciones podrían usarsereduce(..., Infinity)
para coincidir con ese comportamiento. Sin embargo, prefiero que arroje una excepción (como lo hace actualmente), porque tomar el mínimo de una matriz vacía parece ser un error..apply
a menudo se usa cuando la intención es invocar una función variadic con una lista de valores de argumentos, por ej.La
Math.max([value1[,value2, ...]])
función devuelve el mayor de cero o más números.El
Math.max()
método no le permite pasar en una matriz. Si tiene una lista de valores de los cuales necesita obtener el mayor, normalmente llamaría a esta función usando Function.prototype.apply () , por ejemploSin embargo, a partir del ECMAScript 6 puede usar el operador de propagación :
Usando el operador de propagación, lo anterior puede reescribirse como tal:
Al llamar a una función utilizando el operador variable, incluso puede agregar valores adicionales, por ejemplo
Prima:
Operador de difusión le permite utilizar la sintaxis literal de matriz para crear nuevas matrices en situaciones donde en la ES5 que tendría que recurrir al código imperativo, utilizando una combinación de
push
,splice
, etc.fuente
concat
mayoría de los programadores escribirán su último ejemplo en la bonificación porque le permite mantener un estilo de línea única.Dos formas son más cortas y fáciles:
Camino 1 :
Camino 2 :
fuente
0
, puede usar[0].concat(arr)
o con sintaxis extendida[0, ...arr]
(en lugar de 'arr')Lo haces extendiendo el tipo de matriz:
Impulsado desde aquí (por John Resig)
fuente
Una solución simple para encontrar el valor mínimo sobre uno
Array
de los elementos es usar laArray
función prototiporeduce
:o usando la función incorporada Math.Min () de JavaScript (gracias @Tenflex):
Esto se establece
min
enA[0]
, y luego verificaA[1]...A[n]
si es estrictamente menor que el actualmin
. SiA[i] < min
luegomin
se actualiza aA[i]
. Cuando se han procesado todos los elementos de la matriz,min
se devuelve como resultado.EDITAR : Incluir posición de valor mínimo:
fuente
min
valor devuelto sino también su posición en la matriz?Otros ya han dado algunas soluciones en las que aumentan
Array.prototype
. Todo lo que quiero en esta respuesta es aclarar si debería serMath.min.apply( Math, array )
oMath.min.apply( null, array )
. Entonces, ¿qué contexto se debe utilizarMath
onull
?Al pasar
null
como contexto aapply
, el contexto se convertirá por defecto en el objeto global (elwindow
objeto en el caso de los navegadores). Pasar elMath
objeto como contexto sería la solución correcta, pero tampoco le hará daño pasarnull
. Aquí hay un ejemplo de cuándonull
podría causar problemas al decorar laMath.max
función:Lo anterior arrojará una excepción porque
this.foo
se evaluará comowindow.foo
, que esundefined
. Si reemplazamosnull
conMath
, las cosas funcionarán como se esperaba y la cadena "foo" se imprimirá en la pantalla (probé esto usando Mozilla Rhino ).Se puede suponer que nadie lo ha decorado
Math.max
, así que pasarnull
funcionará sin problemas.fuente
Foo.staticMethod
y haría referenciathis
? ¿No sería eso un error en el diseño del decorador? (a menos que, por supuesto, quisieran hacer referencia al alcance global y quieran permanecer independientes del motor de JavaScript que se utiliza, por ejemplo, Rhino).Math.max
, implementado por especificación, no utilizathis
. Si alguien anula deMath.max
tal manera que sí lo usathis
, entonces ha hecho que su comportamiento viole las especificaciones y usted debe arrojarles objetos afilados. No debe codificar alrededor de esa posibilidad más de lo que codificaría alrededor de la posibilidad de que alguien haya cambiadoMath.max
yMath.min
por el lulz.Una forma más de hacerlo:
Uso:
fuente
Metodos alternativos
Los métodos
Math.min
yMath.max
son operaciones recursivas que se agregan a la pila de llamadas del motor JS, y muy probablemente se bloquean para una matriz que contiene una gran cantidad de elementos(más de ~ 10⁷ elementos, depende del navegador del usuario).
En cambio, use algo como esto:
O con mejor tiempo de ejecución:
O para obtener Min y Max:
O con un tiempo de ejecución aún mejor *:
* Probado con 1,000,000 de elementos:
solo como referencia, el tiempo de ejecución de la primera función (en mi máquina) fue de 15.84 ms frente a la segunda función con solo 4.32 ms.
fuente
Esto puede adaptarse a sus propósitos.
fuente
comparer
supone que debe llamarse en algún ámbito específico? Porque como se hace referenciathis[index]
que esundefined
cada vez.Math.xxx
) se ejecuta en el ámbito global ...https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math/max
Esto funcionó para mí.
fuente
Me sorprende que nadie haya mencionado la función de reducción.
fuente
Para grandes matrices (~ 10⁷ elementos),
Math.min
yMath.max
obtiene un RangeError (Tamaño máximo de la pila de llamadas excedido) en node.js.Para matrices grandes, una solución rápida y sucia es:
fuente
Tuve el mismo problema, necesitaba obtener los valores mínimos y máximos de una matriz y, para mi sorpresa, no había funciones integradas para las matrices. Después de leer mucho, decidí probar yo mismo las "3 mejores soluciones":
El código de prueba fue este:
La matriz A se llenó con 100,000 números enteros aleatorios, cada función se ejecutó 10,000 veces en Mozilla Firefox 28.0 en un escritorio Intel Pentium 4 a 2.99GHz con Windows Vista. Los tiempos están en segundos, recuperados por la función performance.now (). Los resultados fueron estos, con 3 dígitos fraccionarios y desviación estándar:
La solución REDUCE fue un 117% más lenta que la solución discreta. La solución APLICAR fue la peor, 2,118% más lenta que la solución discreta. Además, como observó Peter, no funciona para matrices grandes (más de 1,000,000 de elementos).
Además, para completar las pruebas, probé este código discreto extendido:
El tiempo: media = 0.218s, sd = 0.094
Por lo tanto, es un 35% más lento que la solución discreta simple, pero recupera los valores máximos y mínimos al mismo tiempo (cualquier otra solución tomaría al menos el doble para recuperarlos). Una vez que el OP necesitara ambos valores, la solución discreta sería la mejor opción (incluso si dos funciones separadas, una para calcular el máximo y otra para calcular el mínimo, superarían a la segunda mejor, la solución REDUCIR).
fuente
Puede usar la siguiente función en cualquier parte de su proyecto:
Y luego puede llamar a las funciones que pasan la matriz:
fuente
El siguiente código funciona para mí:
fuente
Iterar a través, manteniendo un registro sobre la marcha.
Esto dejará min / max nulo si no hay elementos en la matriz. Establecerá min y max en una pasada si la matriz tiene algún elemento.
También puede extender Array con un
range
método que utiliza lo anterior para permitir la reutilización y mejorar la legibilidad. Vea un violín de trabajo en http://jsfiddle.net/9C9fU/Usado como
fuente
range
función que sería la mejor manera de obtener el mínimo y el máximo al mismo tiempo IMO, como lo hice con una actualización de mi respuesta.Pensé en compartir mi solución simple y fácil de entender.
Para el min:
Y para el máximo:
fuente
for…in
enumeraciones en matrices!Cosas simples, de verdad.
fuente
Aquí hay una forma de obtener el valor máximo de una matriz de objetos. Cree una copia (con corte), luego ordene la copia en orden descendente y tome el primer elemento.
fuente
Usando
Math.max()
oMath.min()
La siguiente función se utiliza
Function.prototype.apply()
para encontrar el elemento máximo en una matriz numérica.getMaxOfArray([1, 2, 3])
es equivalente aMath.max(1, 2, 3)
, pero puede usarlogetMaxOfArray()
en matrices construidas mediante programación de cualquier tamaño.O con el nuevo operador de propagación, obtener el máximo de una matriz se vuelve mucho más fácil.
fuente
Además de usar la función matemática max y min, otra función a usar es la función incorporada de sort (): aquí vamos
fuente
La solución de ChaosPandion funciona si está utilizando un prototipo. Si no, considere esto:
Lo anterior devolverá NaN si un valor de matriz no es un entero, por lo que debe crear alguna funcionalidad para evitar eso. De lo contrario, esto funcionará.
fuente
Math
objeto como contexto?Si usa la biblioteca sugar.js , puede escribir arr.min () y arr.max () como sugiere. También puede obtener valores mínimos y máximos de matrices no numéricas.
Ejemplos:
Bibliotecas como Lo-Dash y underscore.js también proporcionan funciones mínimas y máximas potentes similares:
Ejemplo de Lo-Dash:
fuente
fuente
Tratar
Mostrar fragmento de código
Para Math.min / max (+ apply) obtenemos el error:
Mostrar fragmento de código
fuente