JASoft.org

El blog de José Manuel Alarcón Aguín. Programación web y mucho más...

MENÚ - JASoft: JM Alarcón

El mejor método para vaciar una matriz en JavaScript

Esto surge a raíz de la pregunta de un alumno en mi curso de fundamentos de JavaScript y jQuery, y lo cierto es que es una pregunta sencilla, pero al mismo tiempo interesante...

Si tengo una matriz como esta, por ejemplo:

var miMatriz = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

¿Cómo la vacío?

Bueno, lo más evidente parece asignarle a tu variable una matriz nueva, vacía. Algo así:

miMatriz = [];

Pero realmente no hemos vaciado la matriz. Lo que hemos hecho es crear una nueva matriz vacía y se la hemos asignado a la matriz original. Pero la matriz original sigue viva y coleando en memoria. Si está referenciada por alguna otra variable en tu código quedará en memoria todo el tiempo, ya que el recolector de basura no podrá reclamar el espacio que ocupa. Si la matriz es pequeña, como la que hemos puesto al principio, no influirá lo más mínimo. Pero si es muy grande, con miles de elementos, puede llegar a ser un problema. En cualquier caso, si lo que quieres es tener una referencia a una matriz vacía en tu variable, el método te servirá en muchos casos, pero hay que tener claro qué es lo que se está haciendo.

Otro intento lógico que podemos seguir es retirar, uno a uno en un bucle, todos los elementos de la matriz original, definiendo una función del estilo de esta:

function vaciaMatriz(miArr){
    while(miArr.length > 0) {
        miArr.pop();
    }
}

que recorre todos los elementos de la matriz y se los va quitando uno a uno hasta que no queda ninguno. Con esto nos acercamos más al objetivo, ya que la matriz original queda modificada de verdad, y se vacía. Pero es una idea horrible ya que debe recorrer todos los elementos para hacerlo. En una matriz grande puede tardar, aunque bien es cierto en casi ninguna circunstancia normal vamos a notar siquiera el efecto en el rendimiento de la aplicación.

Vamos a tratar de mejorar...

Otra opción posible es recortar la matriz usando alguno de los métodos de manipular sus elementos, como slice y splice.

El primero no es una buena opción ya que lo que hace slice es en realidad hacer una copia de la matriz entre los índices que le digamos, pero no altera la matriz original, así que aunque escribamos:

miMatriz = miMatriz.slice(0,0);

estamos igual que en el caso anterior: conseguiremos una nueva matriz vacía asignada a la variable, pero la original seguirá estando en memoria.

El caso de splice es mucho más interesante y promete conseguir lo que necesitamos: esta función realmente quita los elementos que le indiquemos a la matriz, empezando por el elemento que le indiquemos en primer lugar y quitando el número de elementos que le digamos como segundo parámetro.

Así que según esto si escribimos:

miMatriz.splice(0, miMatriz.length);

tendríamos realmente el resultado buscado, ya que la matriz original se modifica y en este caso se vacía, pues le estamos diciendo que empiece por el primer elemento y quite todos los que hay en la misma (su longitud).

Con splice sí que podemos conseguir de verdad lo que buscábamos: vaciar la matriz original.

¡Yupi! Parece que tenemos ganadora...

En realidad, esta solución es muy buena y casi tan buena como la "definitiva" que voy a dar a continuación.

Y es que resulta que la mayor parte de las veces lo más sencillo es lo mejor. Y es que en JavaScript podemos conseguir que una matriz se vacía simplemente con esta instrucción:

miMatriz.length = 0

En efecto, si en JavaScript ponemos la longitud de una matriz a cero, automáticamente la vaciamos.

Es una de las bondades de las matrices en este lenguaje: que son dinámicas por naturaleza. Esto significa que si cambiamos su longitud crecen o decrecen según lo necesitemos. Llevando esto al extremo, si le ponemos una longitud de 0, es decir, sin elementos, las vaciamos.

Y esta solución es verdaderamente eficiente y rápida y cumple con la otra condició que poníamos al principio: modificar la matriz original para vaciarla, no solo reasignar la variable a una matriz vacía.

Parece que tenemos ganador definitivo.

Vamos a verlo con haciendo algún benchmark, para lo cual he utilizado JSPerf para probarlo varias veces con una matriz de 2000 elementos para ver cuál ofrece más rendimiento.

Aquí puedes ver los resultados del test de rendimiento de todos los métodos (los puedes realizar con tu propio navegador, tardarán unos pocos segundos, y así copntribuir a probarlos en el mayor número de navegadores y sistemas. No los pongas a la vez en varios navegadores o interferirán: de 1 en 1 mejor si lo pruebas en varios). También he hecho una versión para jsbench.

Resultados del test

Como puedes comprobar, el método de establecer la longitud a 0 es el ganador, aunque ponga en la parte de arriba como ganador al de asignar una matriz vacía que, claro está, es muy rápido, pero como hemos visto tampoco cumple lo que buscábamos. El de la longitud = 0 empata en cuanto a rendimiento pero sí hace exactamente lo que buscábamos.

Como nota resaltable podemos observar que slice y splice también ofrecen un rendimiento muy bueno, pero recordemos que el primero tampoco hace lo que queríamos.

Finalmente, señalar que la gráfica no está a escala (la he recortado para ponerla aquí): el método de vaciar uno a uno tarda enormemente más que lo que reflejan estas barras, y es claramente la peor forma de hacerlo. No tarda el triple o así como pudiera parecer: es muuuucho más lento que los demás, como verás si entras en el enlace anterior.

¡Espero que te resulte útil!

José Manuel Alarcón José Manuel Alarcón
Fundador y director de campusMVP.es, el proyecto de referencia en formación on-line para programadores en lengua española. Autor de varios libros y cientos de artículos. Galardonado como MVP de Microsoft desde 2004. Gallego de Vigo, amante de la ciencia y la tecnología, la música y la lectura. Ayudando a la gente en Internet desde 1996.
Descarga GRATIS mi último libro (no técnico): "Tres Monos, Diez Minutos".
Banner

Comentarios (4) -

uncomentario

¿No sé si te has dado cuenta, pero el fastest no es siempre el mismo? y con diferentes navegadores dan resultado totalmente diferentes, pe. para ie 11, el más rápido es el slice.
¿qué de fiable es esta página de test?

Responder

by Jose M. Alarcon

Mmmm, pues la verdad es que no me había fijado. Hice la prueba un par de veces en Chrome y siempre me daba lo mismo, pero ahora que me lo dices probando con otros navegadores ocurre lo que dices. Repetiré la prueba de alguna manera más fiable y lo pondré aquí. No obstante el resto sigue siendo válido, y los resultados iniciales que he comentado parecen correctos...

Gracias por comentar.

Responder

by Jose M. Alarcon

Hola de nuevo;:

Ya sé lo qué ocurría. No estaba bien definido el test porque en cada vuelta, según el método, la matriz estaba ya vacía cuando se repetía el test. He tenido que rediseñarlo para que funcione en ese sitio y de paso lo he repetido en JSPerf (más conocido) siguiendo el mismo esquema, que es definir la matriz como variable global y asignándola a otra variable global con un slice(0) para que obtener una copia, antes de hacer cada uno de los test. De esta forma va siempre llena y no se falsean los datos.

Ahora tengo las dos pruebas, en JSBench y en JSPerf:
- http://jsben.ch/#/vw9Cd
- jsperf.com/.../1

y en ambos casos da lo que era de esperar y son consistentes entre navegadores.

Lástima que no hayas puesto tu correo verdadero para que te llegue esto :-S

Saludos y gracias por comentar en cualquier caso.

Responder

AUGUSTO CEDENO

En mi caso en Chrome: la opción mas rápida fue: Re-assign the variable

window.arr = myArray.slice(0);
arr = [];

Responder

Agregar comentario