¿Cómo elimino elementos vacíos de una matriz en JavaScript?
¿Hay alguna forma sencilla o necesito recorrerla y eliminarla manualmente?
¿Cómo elimino elementos vacíos de una matriz en JavaScript?
¿Hay alguna forma sencilla o necesito recorrerla y eliminarla manualmente?
Respuestas:
EDITAR: Esta pregunta fue respondida hace casi nueve años cuando no había muchos métodos integrados útiles en el Array.prototype
.
Ahora, ciertamente, te recomendaría que uses el filter
método.
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 "vacío", 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 típico que veo utiliza a menudo es eliminar los elementos que son Falsy , que incluyen una cadena vacía ""
, 0
, NaN
, null
, undefined
, y false
.
Puede pasar al filter
método, la Boolean
función de constructor o 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 filter
método en el primer caso, llama al Boolean
constructor como una función, convirtiendo el valor, y en el segundo caso, el filter
método convierte internamente el valor de retorno de la devolución de llamada implícitamente Boolean
.
Si está trabajando con matrices dispersas y está tratando de deshacerse de los "agujeros", puede usar el filter
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 ]
Antigua respuesta: ¡No hagas esto!
Utilizo este método, extendiendo el prototipo nativo de matriz:
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,,,,]);
splice
llamada es realmente costosa en navegadores antiguos porque tienen que renumerar todas las claves de la matriz para cerrar la brecha.
Array.prototype
uso Object.defineProperty
para hacer que la nueva función sea una propiedad no enumerable y luego evitar el impacto en el rendimiento causado al poner .hasOwnProperty
en cada bucle.
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 única del tipo "texto")
['','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]
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]
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;
arr // [1, 2, 3, 3, 4, 4, 5, 6]
['foo', '',,,'',,null, ' ', 3, true, [], [1], {}, undefined, ()=>{}].filter(String)
// ["foo", null, " ", 3, true, [1], Object {}, undefined, ()=>{}]
arr = arr.filter(function(n){return n; });
foo.join("").split("")
solo parece funcionar si las cadenas son caracteres individuales
arr.filter(e=>e)
y esto se puede encadenar por mapa, reducir, etc.
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});
Regreso:
["hello", 1, 100, " "]
ACTUALIZACIÓN (basado en el comentario de Alnitak)
En algunas situaciones, es posible que desee mantener "0" en la matriz y eliminar cualquier otra cosa (nulo, indefinido y ""), esta es una forma:
arr.filter(function(e){ return e === 0 || e });
Regreso:
["hello", 0, 1, 100, " "]
function(e){return !!e}
!!e
incluirá NaN (a diferencia de 0), mientras e
que whereous no lo haría (como 0).
var myarr=[1, 2,, 3,, 3,undefined,,"",,0, 4,, 4,, 5,, 6,,,,].filter(Boolean);
elimina indefinido, "" y 0
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]
Boolean
funciona como una función ...
Boolean
como una función, simplemente devolverá true
o false
si el valor es verdadero / falso.
(true).constructor === Boolean
. Y luego dime si podemos hacer esto con otros complementos en JS. ;)) (por supuesto excluyó a los otros 5 constructores integrados. (Cadena, matriz, objeto, función, número))
Si tiene Javascript 1.6 o posterior, puede usar Array.filter
una return true
función de devolución de llamada trivial , por ejemplo:
arr = arr.filter(function() { return true; });
ya que .filter
automáticamente omite 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 filter
que se puede usar en intérpretes de JavaScript que no admiten la versión oficial.
Tenga en cuenta que esto no eliminará null
entradas ni entradas con un undefined
valor explícito , pero el OP solicitó específicamente entradas "faltantes".
undefined
como su valor dado.
Para eliminar agujeros, debe usar
arr.filter(() => true)
arr.flat(0) // Currently stage 3, check compatibility before using this
Para eliminar los valores de agujero y falso (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]
[, ,]
arr.filter(x => x)
, JS verificará si x es verdadero o falso, es decir if (x)
, solo el valor de verdad se asignará a la nueva lista.
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"]
undefined
; Esto básicamente elimina todos los valores falsos.
ES6 simple
['a','b','',,,'w','b'].filter(v => v);
[1, 'two', null, undefined, , NaN, false, true, 0].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 envases vacíos:
_.without(['foo', 'bar', '', 'baz', '', '', 'foobar'], '');
--> ["foo", "bar", "baz", "foobar"]
Consulte la documentación de lodash para sin .
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, falso, nulo, 0, "", indefinido 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 adicional. Vea 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;
};
}
let newArr = arr.filter(e => e);
Es posible que le resulte más fácil recorrer su matriz y crear una nueva matriz a partir de los elementos que desea mantener de la matriz que intentando hacer un bucle y unir como se ha sugerido, ya que modifica la longitud de la matriz mientras está en bucle. sobre 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]
Usted tiene la idea: podría tener otros tipos de funciones de filtro. Probablemente más de lo que necesitas, pero me sentía generoso ...;)
Debe usar filter para obtener una matriz sin elementos vacíos. Ejemplo en ES6
const array = [1, 32, 2, undefined, 3];
const newArray = array.filter(arr => arr);
Simplemente estoy añadiendo mi voz a las anteriores “llamar ES5 de Array..filter()
con un constructor mundial” golf-corte, pero se sugiere emplear Object
en lugar de String
, Boolean
oNumber
como se sugirió anteriormente.
Específicamente, los ES5 filter()
ya no activan undefined
elementos dentro de la matriz; Por lo tanto, una función que devuelve universalmente true
, que devuelve todos losfilter()
aciertos de elementos , necesariamente 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 Object
constructor 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 un entorno booleano, 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]
someArray.filter(String);
es decir, en realidad es equivalente a someArray.filter(function(x){ return String(x); });
. Si desea eliminar todos los valores falsos someArray.filter(Boolean);
funciona para eliminar 0, -0, NaN, falso '', nulo e indefinido.
Object
constructor en lugar del return true
método. @robocat, el OP solicitó que se eliminen los elementos vacíos, no los nulos.
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 muestra 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í.
Devoluciones
["some string yay", "Other string yay"]
["", "some string yay", "", "", 123, "Other string yay"].filter(function(n){ return n.length > 0}) //gives your same result removing 123
Reemplazando esa función. .. con String, irónicamente, deja números pero daría el mismo resultado en su matriz dada.
var data = [null, 1,2,3];
var r = data.filter(function(i){ return i != null; })
console.log(r)
[1,2,3]
¿Qué hay de eso?
js> [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,].filter(String).join(',')
1,2,3,3,0,4,4,5,6
join() === join(',')
:)
Esto funciona, lo probé en AppJet (puede copiar y pegar el código en su IDE y presionar "volver 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]
*/
for ... in
que realmente provoca la omisión de elementos faltantes. La prueba undefined
solo sirve para eliminar elementos reales que se establecen explícitamente en ese valor.
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 caso.
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 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 } ) ;
arr.filter(e => e)
.
smart
--como el verbo, para causar un agudo dolor punzante. Esto es relevante debido al dolor físico si uso mi teléfono como arma debido a su comentario.
'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);
for ... in
es lo que elimina las claves indefinidas de la matriz, pero en realidad no hay ningún código aquí para aceptar solo valores "verdaderos"
Esto podría ayudarlo: https://lodash.com/docs/4.17.4#remove
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.
Si una matriz contiene objetos, matrices y cadenas vacíos junto con otros elementos vacíos, podemos eliminarlos con:
const arr = [ [], ['not', 'empty'], {}, { key: 'value' }, 0, 1, null, 2, "", "here", " ", 3, undefined, 3, , , , , , 4, , 4, , 5, , 6, , , ]
let filtered = JSON.stringify(
arr.filter((obj) => {
return ![null, undefined, ''].includes(obj)
}).filter((el) => {
return typeof el != "object" || Object.keys(el).length > 0
})
)
console.log(JSON.parse(filtered))
Con ES6:
const arr = [0, 1, null, 2, "", 3, undefined, 3, , , , , , 4, , 4, , 5, , 6, , , ,]
let filtered = arr.filter((obj) => { return ![null, undefined].includes(obj) })
console.log(filtered)
Con Javascript simple ->
var arr = [0, 1, null, 2, "", 3, undefined, 3, , , , , , 4, , 4, , 5, , 6, , , ,]
var filtered = arr.filter(function (obj) { return ![null, undefined].includes(obj) })
console.log(filtered)
Filtrar entradas no válidas con una expresión regular
array = array.filter(/\w/);
filter + regexp
La mejor manera de eliminar elementos vacíos es usar Array.prototype.filter()
, como ya se mencionó en otras respuestas.
Lamentablemente, 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 el siguiente polyfill para agregar compatibilidad 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;
};
}
var a = [,,]
yvar a = [undefined, undefined]
. El primero está realmente vacío, pero el segundo en realidad tiene dos claves, pero conundefined
valores.