¿La forma más eficiente de crear una matriz JavaScript llena de ceros?
¿Cuál es la forma más eficiente de crear una matriz llena de ceros de longitud arbitraria en JavaScript?
ES6 presenta Array.prototype.fill
. Se puede utilizar así:
new Array(len).fill(0);
No estoy seguro de si es rápido, pero me gusta porque es breve y autodescriptivo.
Todavía no está en IE ( verifique la compatibilidad ), pero hay un polyfill disponible .
Aunque este es un hilo viejo, quería agregarle mis 2 centavos. No estoy seguro de qué tan lento/rápido es esto, pero es una frase rápida. Esto es lo que hago:
Si quiero precompletar con un número:
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]
Si quiero precompletar con una cadena:
Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]
Otras respuestas han sugerido:
new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]
pero si quieres 0 (el número) y no "0" (cero dentro de una cadena), puedes hacer:
new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]
En breve
Solución más rápida:
let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;
La solución más corta (útil) (3 veces más lenta para matrices pequeñas, ligeramente más lenta para matrices grandes (más lenta en Firefox))
Array(n).fill(0)
Detalles
Hoy 09.06.2020 realizo pruebas en macOS High Sierra 10.13.6 en los navegadores Chrome 83.0, Firefox 77.0 y Safari 13.1. Pruebo las soluciones elegidas para dos casos de prueba.
- pequeña matriz - con 10 elementos - puede realizar la prueba AQUÍ
- matrices grandes, con elementos de 1 millón, puede realizar la prueba AQUÍ
Conclusiones
- La solución basada en
new Array(n)+for
(N) es la solución más rápida para matrices pequeñas y grandes (excepto Chrome, pero sigue siendo muy rápida allí) y se recomienda como solución rápida para varios navegadores. - La solución basada en
new Float32Array(n)
(I) devuelve una matriz no típica (por ejemplo, no se puede llamarpush(..)
a ella), por lo que no comparo sus resultados con otras soluciones; sin embargo, esta solución es entre 10 y 20 veces más rápida que otras soluciones para matrices grandes en todos los navegadores. - Las soluciones basadas en
for
(L,M,N,O) son rápidas para arreglos pequeños. - Las soluciones basadas en
fill
(B,C) son rápidas en Chrome y Safari, pero sorprendentemente más lentas en Firefox para matrices grandes. Son medianamente rápidos para arreglos pequeños. - la solución basada en
Array.apply
(P) arroja un error para matrices grandesMostrar fragmento de código
Código y ejemplo
El siguiente código presenta las soluciones utilizadas en las mediciones.
Mostrar fragmento de código
Resultados de ejemplo para Chrome:
Manera elegante de llenar una matriz con valores precalculados
Aquí hay otra forma de hacerlo usando ES6 que nadie ha mencionado hasta ahora:
> Array.from(Array(3), () => 0)
< [0, 0, 0]
Funciona pasando una función de mapa como segundo parámetro de Array.from
.
En el ejemplo anterior, el primer parámetro asigna una matriz de 3 posiciones llenas con el valor undefined
y luego la función lambda asigna cada una de ellas al valor 0
.
Aunque Array(len).fill(0)
es más corto, no funciona si necesita llenar la matriz haciendo algunos cálculos primero (sé que la pregunta no lo pedía, pero mucha gente termina aquí buscando esto) .
Por ejemplo, si necesitas una matriz con 10 números aleatorios:
> Array.from(Array(10), () => Math.floor(10 * Math.random()))
< [3, 6, 8, 1, 9, 3, 0, 6, 7, 1]
Es más conciso (y elegante) que su equivalente:
const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
numbers[i] = Math.round(10 * Math.random());
}
Este método también se puede utilizar para generar secuencias de números aprovechando el parámetro de índice proporcionado en la devolución de llamada:
> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Respuesta adicional: llene una matriz usando Stringrepeat()
Dado que esta respuesta está recibiendo mucha atención, también quería mostrar este genial truco. Aunque no es tan útil como mi respuesta principal, presentaré el repeat()
método String aún no muy conocido, pero muy útil. Aquí está el truco:
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
Genial, ¿eh? repeat()
Es un método muy útil para crear una cadena que es la repetición de la cadena original un número determinado de veces. Después de eso, split()
crea una matriz para nosotros, que luego se map()
envía a los valores que queremos. Desglosándolo en pasos:
> "?".repeat(10)
< "??????????"
> "?".repeat(10).split("")
< ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]