Pregunta

¿Cómo elimino elementos vacíos de una matriz en JavaScript?

¿Hay alguna forma sencilla o necesito recorrerla y eliminarla manualmente?

¿Fue útil?

Solución

EDITAR: Esta pregunta fue respondida hace casi 9 años, cuando no había muchos métodos integrados útiles en el Array.prototype.

Ahora, ciertamente te recomendaría que uses el método filter.

Tenga en cuenta que este método le devolverá una nueva matriz con los elementos que pasan los criterios de la función de devolución de llamada que le proporciona, por ejemplo, si desea eliminar null o undefined valores:

var array = [0, 1, null, 2, "", 3, undefined, 3,,,,,, 4,, 4,, 5,, 6,,,,];

var filtered = array.filter(function (el) {
  return el != null;
});

console.log(filtered);

Dependerá de lo que considere " empty " ;, por ejemplo, si se trata de cadenas, la función anterior no eliminaría los elementos que son una cadena vacía.

Un patrón común que veo que se usa con frecuencia es eliminar elementos que son falso , que incluyen una cadena vacía "", 0, NaN, false, Boolean y <=>.

Puede simplemente pasar al método <=>, la función constructora <=>, o simplemente devolver el mismo elemento en la función de criterios de filtro, por ejemplo:

var filtered = array.filter(Boolean);

O

var filtered = array.filter(function(el) { return el; });

En ambos sentidos, esto funciona porque el método <=> en el primer caso, llama al constructor <=> como una función, convierte el valor, y en el segundo caso, el método <=> convierte internamente el valor de retorno de la devolución de llamada implícitamente a <=>.

Si está trabajando con matrices dispersas y está tratando de deshacerse de " agujeros " ;, simplemente puede usar el método <=> pasando una devolución de llamada que devuelve verdadero, por ejemplo :

var sparseArray = [0, , , 1, , , , , 2, , , , 3],
    cleanArray = sparseArray.filter(function () { return true });

console.log(cleanArray); // [ 0, 1, 2, 3 ]

Respuesta anterior: ¡No hagas esto!

Utilizo este método, extendiendo el prototipo de matriz nativa:

Array.prototype.clean = function(deleteValue) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == deleteValue) {         
      this.splice(i, 1);
      i--;
    }
  }
  return this;
};

test = new Array("", "One", "Two", "", "Three", "", "Four").clean("");
test2 = [1, 2,, 3,, 3,,,,,, 4,, 4,, 5,, 6,,,,];
test2.clean(undefined);

O simplemente puede insertar los elementos existentes en otra matriz:

// Will remove all falsy values: undefined, null, 0, false, NaN and "" (empty string)
function cleanArray(actual) {
  var newArray = new Array();
  for (var i = 0; i < actual.length; i++) {
    if (actual[i]) {
      newArray.push(actual[i]);
    }
  }
  return newArray;
}

cleanArray([1, 2,, 3,, 3,,,,,, 4,, 4,, 5,, 6,,,,]);

Otros consejos

Formas simples:

var arr = [1,2,,3,,-3,null,,0,,undefined,4,,4,,5,,6,,,,];


arr.filter(n => n)
// [1, 2, 3, -3, 4, 4, 5, 6]

arr.filter(Number) 
// [1, 2, 3, -3, 4, 4, 5, 6]

arr.filter(Boolean) 
// [1, 2, 3, -3, 4, 4, 5, 6]

o - (solo para elementos de matriz individuales de tipo "text")

['','1','2',3,,'4',,undefined,,,'5'].join('').split(''); 
// output:  ["1","2","3","4","5"]

o - Forma clásica: iteración simple

var arr = [1,2,null, undefined,3,,3,,,0,,,[],,{},,5,,6,,,,],
    len = arr.length, i;

for(i = 0; i < len; i++ )
    arr[i] && arr.push(arr[i]);  // copy non-empty values to the end of the array

arr.splice(0 , len);  // cut the array and leave only the non-empty values

arr // [1,2,3,3,[],Object{},5,6]


a través de jQuery:

var arr = [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,];

arr = $.grep(arr,function(n){ return n == 0 || n });

arr // [1, 2, 3, 3, 0, 4, 4, 5, 6]


ACTUALIZACIÓN - solo otra forma rápida y genial (usando ES6):

var arr = [1,2,null, undefined,3,,3,,,0,,,4,,4,,5,,6,,,,], 
    temp = [];

for(let i of arr)
    i && temp.push(i); // copy each non-empty value to the 'temp' array

arr = temp;
delete temp; // discard the variable

arr // [1, 2, 3, 3, 4, 4, 5, 6]

Eliminar valores vacíos

['foo', '',,,'',,null, ' ', 3, true, [], [1], {}, undefined, ()=>{}].filter(String)

// ["foo", null, " ", 3, true, [1], Object {}, undefined, ()=>{}]

Si necesita eliminar TODOS los valores vacíos (" " ;, nulo, indefinido y 0):

arr = arr.filter(function(e){return e}); 

Para eliminar valores vacíos y saltos de línea:

arr = arr.filter(function(e){ return e.replace(/(\r\n|\n|\r)/gm,"")});

Ejemplo:

arr = ["hello",0,"",null,undefined,1,100," "]  
arr.filter(function(e){return e});

Volver:

["hello", 1, 100, " "]

ACTUALIZACIÓN (según el comentario de Alnitak)

En algunas situaciones es posible que desee mantener " 0 " en la matriz y elimine cualquier otra cosa (nulo, indefinido y " "), esta es una forma:

arr.filter(function(e){ return e === 0 || e });

Volver:

["hello", 0, 1, 100, " "]

Simplemente un revestimiento:

[1, false, "", undefined, 2].filter(Boolean); // [1, 2]

o usando underscorejs.org :

_.filter([1, false, "", undefined, 2], Boolean); // [1, 2]
// or even:
_.compact([1, false, "", undefined, 2]); // [1, 2]

Si tiene Javascript 1.6 o posterior, puede usar Array.filter utilizando una función de devolución de llamada trivial return true , por ejemplo:

arr = arr.filter(function() { return true; });

ya que .filter omite automáticamente los elementos que faltan en la matriz original.

La página MDN vinculada anteriormente también contiene una buena versión de verificación de errores de filter que se puede utilizar en intérpretes de JavaScript que no admiten la versión oficial.

Tenga en cuenta que esto no eliminará las entradas null ni las entradas con un valor explícito undefined , pero el OP solicitó específicamente "falta". entradas.

Para eliminar agujeros, debe usar

arr.filter(() => true)
arr.flat(0) // Currently stage 3, check compatibility before using this

Para eliminar agujeros y valores falsos (nulo, indefinido, 0, -0, NaN, " " ;, falso, document.all):

arr.filter(x => x)

Para eliminar agujeros, nulos e indefinidos:

arr.filter(x => x != null)

arr = [, null, (void 0), 0, -0, NaN, false, '', 42];
console.log(arr.filter(() => true)); // [null, (void 0), 0, -0, NaN, false, '', 42]
console.log(arr.filter(x => x)); // [42]
console.log(arr.filter(x => x != null)); // [0, -0, NaN, false, "", 42]

La forma limpia de hacerlo.

var arr = [0,1,2,"Thomas","false",false,true,null,3,4,undefined,5,"end"];
arr = arr.filter(Boolean);
// [1, 2, "Thomas", "false", true, 3, 4, 5, "end"]

Simple ES6

['a','b','',,,'w','b'].filter(v => v);

Con subrayado / Lodash:

Caso de uso general:

_.without(array, emptyVal, otherEmptyVal);
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);

Con vacíos:

_.without(['foo', 'bar', '', 'baz', '', '', 'foobar'], '');
--> ["foo", "bar", "baz", "foobar"]

Consulte documentación de lodash para sin .

Solo ES6 y el método de versiones más nuevas, suponga que la matriz está debajo:

 const arr = [1,2,3,undefined,4,5,6,undefined,7,8,undefined,undefined,0,9];

Forma simple:

 const clearArray = arr.filter( i => i );

Si usar una biblioteca es una opción, sé que underscore.js tiene una función llamada compact () http: // documentcloud.github.com/underscore/ también tiene varias otras funciones útiles relacionadas con matrices y colecciones.

Aquí hay un extracto de su documentación:

  

_.compact (matriz)

     

Devuelve una copia de la matriz con todos los valores falsos eliminados. En JavaScript, false, null, 0, " " ;, undefined y NaN son falsos.

     

_.compact ([0, 1, falso, 2, '', 3]);

     

= > [1, 2, 3]

@Alnitak

En realidad Array.filter funciona en todos los navegadores si agrega algún código extra. Ver abajo.

var array = ["","one",0,"",null,0,1,2,4,"two"];

function isempty(x){
if(x!=="")
    return true;
}
var res = array.filter(isempty);
document.writeln(res.toJSONString());
// gives: ["one",0,null,0,1,2,4,"two"]  

Este es el código que necesita agregar para IE, pero el filtro y la programación funcional vale la pena.

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array();
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
      {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
}

Como nadie más lo mencionó y la mayoría de las personas tienen guiones bajos incluidos en su proyecto, también puede usar _.without (array, * values); .

_.without(["text", "string", null, null, null, "text"], null)
// => ["text", "string", "text"]

Puede que le resulte más fácil recorrer su matriz y construir una nueva matriz a partir de los elementos que desea mantener de la matriz que tratando de hacer un bucle y unir como se ha sugerido, ya que modifica la longitud de la matriz mientras si se repite puede introducir problemas.

Podrías hacer algo como esto:

function removeFalsyElementsFromArray(someArray) {
    var newArray = [];
    for(var index = 0; index < someArray.length; index++) {
        if(someArray[index]) {
            newArray.push(someArray[index]);
        }
    }
    return newArray;
}

En realidad, aquí hay una solución más genérica:

function removeElementsFromArray(someArray, filter) {
    var newArray = [];
    for(var index = 0; index < someArray.length; index++) {
        if(filter(someArray[index]) == false) {
            newArray.push(someArray[index]);
        }
    }
    return newArray;
}

// then provide one or more filter functions that will 
// filter out the elements based on some condition:
function isNullOrUndefined(item) {
    return (item == null || typeof(item) == "undefined");
}

// then call the function like this:
var myArray = [1,2,,3,,3,,,,,,4,,4,,5,,6,,,,];
var results = removeElementsFromArray(myArray, isNullOrUndefined);

// results == [1,2,3,3,4,4,5,6]

Se le ocurre la idea: podría tener otros tipos de funciones de filtro. Probablemente más de lo que necesitas, pero me sentía generoso ...;)

ES6: let newArr = arr.filter(e => e);

¿Qué pasa con esto (ES6) ?: Para eliminar el valor de Falsy de una matriz.

var arr = [0,1,2,"test","false",false,true,null,3,4,undefined,5,"end"];

arr.filter((v) => (!!(v)==true));

//output:

//[1, 2, "test", "false", true, 3, 4, 5, "end"]

Debería usar filter para obtener & nbsp; array sin elementos vacíos. Ejemplo en ES6

const array = [1, 32, 2, undefined, 3];
const newArray = array.filter(arr => arr);

Simplemente estoy agregando mi voz a lo anterior & # 8220; llame al Array..filter () de ES5 con un constructor global & # 8221; golf-hack, pero sugiero usar Object en lugar de String , Boolean o Number como se sugirió anteriormente.

Específicamente, el filter () de ES5 ya no se activa para elementos indefinidos dentro de la matriz; por lo tanto, una función que universalmente devuelve true , que devuelve todos elementos filter () hits, necesariamente solo devolverá no undefined elementos:

> [1,,5,6,772,5,24,5,'abc',function(){},1,5,,3].filter(function(){return true})
[1, 5, 6, 772, 5, 24, 5, 'abc', function (){}, 1, 5, 3]

Sin embargo, escribir ... (function () {return true;}) es más largo que escribir ... (Object) ; y el valor de retorno del constructor Object será, bajo cualquier circunstancia , algún tipo de objeto. A diferencia de los constructores de boxeo primitivo sugeridos anteriormente, ningún valor de objeto posible es falsey y, por lo tanto, en una configuración booleana, Object es una abreviatura de function () {return true} .

> [1,,5,6,772,5,24,5,'abc',function(){},1,5,,3].filter(Object)
[1, 5, 6, 772, 5, 24, 5, 'abc', function (){}, 1, 5, 3]

Cuando utilicé la respuesta más votada arriba, primer ejemplo, estaba obteniendo caracteres individuales para longitudes de cadena superiores a 1. A continuación se encuentra mi solución para ese problema.

var stringObject = ["", "some string yay", "", "", "Other string yay"];
stringObject = stringObject.filter(function(n){ return n.length > 0});

En lugar de no regresar si no está definido, devolvemos si la longitud es mayor que 0. Espero que ayude a alguien por ahí.

Voluciones

["some string yay", "Other string yay"]
var data = [null, 1,2,3];
var r = data.filter(function(i){ return i != null; })

console.log(r) 
  

[1,2,3]

¿Qué pasa con eso?

js> [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,].filter(String).join(',')
1,2,3,3,0,4,4,5,6

Esto funciona, lo probé en AppJet (puede copiar y pegar el código en su IDE y presionar " ; vuelva a cargar " para verlo funcionar, no es necesario crear una cuenta)

/* appjet:version 0.1 */
function Joes_remove(someArray) {
    var newArray = [];
    var element;
    for( element in someArray){
        if(someArray[element]!=undefined ) {
            newArray.push(someArray[element]);
        }
    }
    return newArray;
}

var myArray2 = [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,];

print("Original array:", myArray2);
print("Clenased array:", Joes_remove(myArray2) );
/*
Returns: [1,2,3,3,0,4,4,5,6]
*/

Otra forma de hacerlo es aprovechar la propiedad de longitud de la matriz: empaque los elementos no nulos en la 'izquierda' de la matriz y luego reduzca la longitud. Es un algoritmo in situ -no asigna memoria, demasiado malo para el recolector de basura-, y tiene muy buen comportamiento de mejor / promedio / peor de los casos.

Esta solución, en comparación con otras aquí, es entre 2 y 50 veces más rápida en Chrome y de 5 a 50 veces más rápida en Firefox, como puede ver aquí: http://jsperf.com/remove-null-items-from-array

El siguiente código agrega el método 'removeNull' no enumerable a la matriz, que devuelve 'this' para el encadenamiento:

var removeNull = function() {
    var nullCount = 0           ;
    var length    = this.length ;
    for (var i=0, len=this.length; i<len; i++) { if (!this[i]) {nullCount++} }
    // no item is null
    if (!nullCount) { return this}
    // all items are null
    if (nullCount == length) { this.length = 0; return this }
    // mix of null // non-null
    var idest=0, isrc=length-1;
    length -= nullCount ;                
    while (true) {
         // find a non null (source) slot on the right
         while (!this[isrc])  { isrc--; nullCount--; } 
         if    (!nullCount) { break }       // break if found all null
         // find one null slot on the left (destination)
         while ( this[idest]) { idest++  }  
         // perform copy
         this[idest]=this[isrc];
         if (!(--nullCount)) {break}
         idest++;  isrc --; 
    }
    this.length=length; 
    return this;
};  

Object.defineProperty(Array.prototype, 'removeNull', 
                { value : removeNull, writable : true, configurable : true } ) ;
foo = [0, 1, 2, "", , false, 3, "four", null]

foo.filter(function(e) {
    return e === 0 ? '0' : e
})

devoluciones

[0, 1, 2, 3, "four"]

'Uso indebido' del bucle for ... in (objeto-miembro).   = > Solo los valores verdaderos aparecen en el cuerpo del bucle.

// --- Example ----------
var field = [];

field[0] = 'One';
field[1] = 1;
field[3] = true;
field[5] = 43.68;
field[7] = 'theLastElement';
// --- Example ----------

var originalLength;

// Store the length of the array.
originalLength = field.length;

for (var i in field) {
  // Attach the truthy values upon the end of the array. 
  field.push(field[i]);
}

// Delete the original range within the array so that
// only the new elements are preserved.
field.splice(0, originalLength);

Esto podría ayudarlo: https://lodash.com/docs/4.17.4# eliminar

var details = [
            {
                reference: 'ref-1',
                description: 'desc-1',
                price: 1
            }, {
                reference: '',
                description: '',
                price: ''
            }, {
                reference: 'ref-2',
                description: 'desc-2',
                price: 200
            }, {
                reference: 'ref-3',
                description: 'desc-3',
                price: 3
            }, {
                reference: '',
                description: '',
                price: ''
            }
        ];

        scope.removeEmptyDetails(details);
        expect(details.length).toEqual(3);

scope.removeEmptyDetails = function(details){
            _.remove(details, function(detail){
                return (_.isEmpty(detail.reference) && _.isEmpty(detail.description) && _.isEmpty(detail.price));
            });
        };
var data= { 
    myAction: function(array){
        return array.filter(function(el){
           return (el !== (undefined || null || ''));
        }).join(" ");
    }
}; 
var string = data.myAction(["I", "am","", "working", "", "on","", "nodejs", "" ]);
console.log(string);

Salida:

  

Estoy trabajando en nodejs

Eliminará el elemento vacío de la matriz y mostrará otro elemento.

Filtrando entradas inválidas con una expresión regular

array = array.filter(/\w/);
filter + regexp

La mejor manera de eliminar elementos vacíos es utilizar Array.prototype.filter () , como ya se mencionó en otras respuestas.

Desafortunadamente, Array.prototype.filter () no es compatible con IE < 9. Si aún necesita admitir IE8 o una versión aún más antigua de IE, puede usar lo siguiente polyfill para agregar soporte para Array.prototype.filter () en estos navegadores:

if (!Array.prototype.filter) {
  Array.prototype.filter = function(fun/*, thisArg*/) {
    'use strict';
    if (this === void 0 || this === null) {
      throw new TypeError();
    }
    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== 'function') {
      throw new TypeError();
    }
    var res = [];
    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++) {
      if (i in t) {
        var val = t[i];
        if (fun.call(thisArg, val, i, t)) {
          res.push(val);
        }
      }
    }
    return res;
  };
}

Si alguien está buscando limpiar toda la matriz u objeto, esto podría ayudar .

var qwerty = {
    test1: null,
    test2: 'somestring',
    test3: 3,
    test4: {},
    test5: {
        foo: "bar"
    },
    test6: "",
    test7: undefined,
    test8: " ",
    test9: true,
    test10: [],
    test11: ["77","88"],
    test12: {
        foo: "foo",
        bar: {
            foo: "q",
            bar: {
                foo:4,
                bar:{}
            }
        },
        bob: {}
    }
}

var asdfg = [,,"", " ", "yyyy", 78, null, undefined,true, {}, {x:6}, [], [2,3,5]];

function clean_data(obj) {
    for (var key in obj) {
        // Delete null, undefined, "", " "
        if (obj[key] === null || obj[key] === undefined || obj[key] === "" || obj[key] === " ") {
            delete obj[key];
        }
        // Delete empty object
        // Note : typeof Array is also object
        if (typeof obj[key] === 'object' && Object.keys(obj[key]).length <= 0) {
            delete obj[key];
        }
        // If non empty object call function again
        if(typeof obj[key] === 'object'){
            clean_data(obj[key]);
        }
    }
    return obj;
}

var objData = clean_data(qwerty);
console.log(objData);
var arrayData = clean_data(asdfg);
console.log(arrayData);

Salida :

Elimina todo lo que sea nulo , undefined , " " , " " , objeto vacío o matriz vacía

jsfiddle aquí

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top