Come rimuovo elementi vuoti da un array in JavaScript?
Esiste un modo semplice o devo scorrere e rimuoverlo manualmente?
Come rimuovo elementi vuoti da un array in JavaScript?
Esiste un modo semplice o devo scorrere e rimuoverlo manualmente?
Risposte:
EDIT: a questa domanda è stata data risposta quasi nove anni fa quando non c'erano molti metodi incorporati utili in Array.prototype
.
Ora, certamente, ti consiglierei di usare il filter
metodo.
Tieni presente che questo metodo ti restituirà un nuovo array con gli elementi che passano i criteri della funzione di callback che gli fornisci.
Ad esempio, se si desidera rimuovere null
o undefined
valori:
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);
Dipenderà da ciò che consideri "vuoto", ad esempio, se hai a che fare con le stringhe, la funzione sopra non rimuove gli elementi che sono una stringa vuota.
Uno schema tipico che vedo spesso usato è di rimuovere elementi che sono falsy , che includono una stringa vuota ""
, 0
, NaN
, null
, undefined
, e false
.
È possibile passare al filter
metodo, alla Boolean
funzione di costruzione o restituire lo stesso elemento nella funzione dei criteri di filtro, ad esempio:
var filtered = array.filter(Boolean);
O
var filtered = array.filter(function(el) { return el; });
In entrambi i modi, questo funziona perché il filter
metodo nel primo caso chiama il Boolean
costruttore come una funzione, convertendo il valore e nel secondo caso il filter
metodo trasforma implicitamente il valore restituito del callback Boolean
.
Se si lavora con array sparsi e si sta cercando di eliminare i "buchi", è possibile utilizzare il filter
metodo passando un callback che restituisce true, ad esempio:
var sparseArray = [0, , , 1, , , , , 2, , , , 3],
cleanArray = sparseArray.filter(function () { return true });
console.log(cleanArray); // [ 0, 1, 2, 3 ]
Vecchia risposta: non farlo!
Uso questo metodo, estendendo il prototipo di array nativo:
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);
Oppure puoi semplicemente inserire gli elementi esistenti in un altro array:
// 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
chiamata è molto costosa sui browser più vecchi perché devono rinumerare tutti i tasti dell'array per colmare il divario.
Array.prototype
usando Object.defineProperty
per rendere la nuova funzione una proprietà non enumerabile e quindi evitare il colpo di prestazione causato inserendo .hasOwnProperty
ogni ciclo.
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]
oppure - (solo per gli elementi a matrice singola di tipo "testo")
['','1','2',3,,'4',,undefined,,,'5'].join('').split('');
// output: ["1","2","3","4","5"]
oppure - Modo classico: iterazione semplice
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("")
sembra funzionare solo se le stringhe sono caratteri singoli
arr.filter(e=>e)
e questo può essere incatenato per mappa, riduzione, ecc.
Se è necessario rimuovere TUTTI i valori vuoti ("", null, non definito e 0):
arr = arr.filter(function(e){return e});
Per rimuovere valori vuoti e interruzioni di riga:
arr = arr.filter(function(e){ return e.replace(/(\r\n|\n|\r)/gm,"")});
Esempio:
arr = ["hello",0,"",null,undefined,1,100," "]
arr.filter(function(e){return e});
Ritorno:
["hello", 1, 100, " "]
AGGIORNAMENTO (basato sul commento di Alnitak)
In alcune situazioni potresti voler mantenere "0" nell'array e rimuovere qualsiasi altra cosa (null, indefinito e ""), questo è un modo:
arr.filter(function(e){ return e === 0 || e });
Ritorno:
["hello", 0, 1, 100, " "]
function(e){return !!e}
!!e
includerà NaN (a differenza di 0) dove e
non sarebbe (come 0).
var myarr=[1, 2,, 3,, 3,undefined,,"",,0, 4,, 4,, 5,, 6,,,,].filter(Boolean);
rimuove indefinito, "" e 0
Semplicemente una fodera:
[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
funzioni come funzione ...
Boolean
come una funzione, semplicemente restituirà true
o false
se il valore è veramente / falso.
(true).constructor === Boolean
. E poi dimmi se possiamo farlo con altri build-in in JS. ;)) (ovviamente escluso gli altri 5 costruttori incorporati. (String, Array, Object, Function, Number))
Se hai Javascript 1.6 o versioni successive puoi Array.filter
utilizzare una banale return true
funzione di callback, ad esempio:
arr = arr.filter(function() { return true; });
poiché .filter
salta automaticamente gli elementi mancanti nell'array originale.
La pagina MDN collegata sopra contiene anche una buona versione di controllo degli errori filter
che può essere utilizzata negli interpreti JavaScript che non supportano la versione ufficiale.
Si noti che ciò non rimuoverà le null
voci né le voci con un undefined
valore esplicito , ma l'OP ha specificamente richiesto voci "mancanti".
undefined
come valore dato.
Per rimuovere i fori, è necessario utilizzare
arr.filter(() => true)
arr.flat(0) // Currently stage 3, check compatibility before using this
Per rimuovere i valori hole, e, falsy (null, undefined, 0, -0, NaN, "", false, document.all):
arr.filter(x => x)
Per rimuovere hole, null e, non definito:
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 verificherà se x è veritiero o falso, ovvero if (x)
, pertanto, solo il valore di verità verrà assegnato al nuovo elenco.
Il modo pulito per farlo.
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
; questo sostanzialmente rimuove tutti i valori falsi.
Con Underscore / Lodash:
Caso d'uso generale:
_.without(array, emptyVal, otherEmptyVal);
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
Con vuoti:
_.without(['foo', 'bar', '', 'baz', '', '', 'foobar'], '');
--> ["foo", "bar", "baz", "foobar"]
Se usare una libreria è un'opzione, so underscore.js ha una funzione chiamata compact () http://documentcloud.github.com/underscore/ ha anche molte altre utili funzioni relative ad array e raccolte.
Ecco un estratto dalla loro documentazione:
_.compact (array)
Restituisce una copia dell'array con tutti i valori di falsy rimossi. In JavaScript, false, null, 0, "", undefined e NaN sono tutti falsi.
_.compact ([0, 1, false, 2, '', 3]);
=> [1, 2, 3]
@Alnitak
In realtà Array.filter funziona su tutti i browser se aggiungi del codice aggiuntivo. Vedi sotto.
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"]
Questo è il codice che devi aggiungere per IE, ma vale la pena applicare il filtro e la programmazione funzionale.
//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;
};
}
Dal momento che nessun altro lo ha menzionato e la maggior parte delle persone ha sottolineato il carattere di sottolineatura incluso nel loro progetto, è anche possibile utilizzare _.without(array, *values);
.
_.without(["text", "string", null, null, null, "text"], null)
// => ["text", "string", "text"]
let newArr = arr.filter(e => e);
Potresti trovare più facile passare in rassegna il tuo array e creare un nuovo array dagli elementi che desideri mantenere dall'array piuttosto che provare a eseguire il loop e la giunzione come è stato suggerito, dal momento che modificando la lunghezza dell'array mentre è in loop oltre può introdurre problemi.
Potresti fare qualcosa del genere:
function removeFalsyElementsFromArray(someArray) {
var newArray = [];
for(var index = 0; index < someArray.length; index++) {
if(someArray[index]) {
newArray.push(someArray[index]);
}
}
return newArray;
}
In realtà ecco una soluzione più generica:
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]
Ti viene l'idea: potresti quindi avere altri tipi di funzioni di filtro. Probabilmente più del necessario, ma mi sentivo generoso ...;)
È necessario utilizzare il filtro per ottenere l'array senza elementi vuoti. Esempio su ES6
const array = [1, 32, 2, undefined, 3];
const newArray = array.filter(arr => arr);
Sto semplicemente aggiungendo la mia voce al di sopra “chiamata ES5 di Array..filter()
con un costruttore globale” golf-hack, ma io suggerisco di usare Object
al posto di String
, Boolean
oNumber
come suggerito sopra.
In particolare, ES5 filter()
non si attiva già per gli undefined
elementi all'interno dell'array; quindi una funzione che restituisce universalmente true
, che restituisce tutti gli elementi filter()
colpiti, restituirà necessariamente solo non undefined
elementi:
> [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]
Tuttavia, scrivere ...(function(){return true;})
è più lungo della scrittura ...(Object)
; e il valore di ritorno del Object
costruttore sarà, in ogni caso , una sorta di oggetto. A differenza dei costruttori di boxe primitivi suggeriti sopra, nessun valore-oggetto possibile è falso, e quindi in un ambiente booleano, Object
è una scorciatoia per 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);
è effettivamente equivalente someArray.filter(function(x){ return String(x); });
. Se si desidera rimuovere tutti i valori di falsy someArray.filter(Boolean);
funziona per rimuovere 0, -0, NaN, false, '', null e undefined.
Object
costruttore in contrapposizione al return true
metodo. @robocat l'OP ha chiesto di rimuovere elementi vuoti, non null.
Quando ho usato la risposta più votata sopra, nel primo esempio, ho ricevuto caratteri individuali per lunghezze di stringa superiori a 1. Di seguito è la mia soluzione per quel problema.
var stringObject = ["", "some string yay", "", "", "Other string yay"];
stringObject = stringObject.filter(function(n){ return n.length > 0});
Invece di non tornare se non definito, torniamo se la lunghezza è maggiore di 0. Spero che aiuti qualcuno là fuori.
ritorna
["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
sostituendo quella funzione. .. con String, ironia della sorte, lascia i numeri ma darebbe lo stesso risultato nel tuo array dato.
var data = [null, 1,2,3];
var r = data.filter(function(i){ return i != null; })
console.log(r)
[1,2,3]
Che dire di questo:
js> [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,].filter(String).join(',')
1,2,3,3,0,4,4,5,6
join() === join(',')
:)
Funziona, l'ho provato in AppJet (puoi copiare e incollare il codice sul suo IDE e premere "ricaricare" per vederlo funzionare, non è necessario creare un account)
/* 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
che provoca effettivamente il salto degli elementi mancanti. Il test undefined
serve solo a rimuovere elementi reali che sono esplicitamente impostati su quel valore.
Un altro modo per farlo è sfruttare la proprietà length dell'array: comprimere gli elementi non nulli sulla "sinistra" dell'array, quindi ridurre la lunghezza. È un algoritmo sul posto -non alloca la memoria, peccato per il garbage collector-, e ha un comportamento molto buono / medio / peggiore.
Questa soluzione, rispetto ad altre qui, è da 2 a 50 volte più veloce su Chrome e da 5 a 50 volte più veloce su Firefox, come potresti vedere qui: http://jsperf.com/remove-null-items-from-array
Il codice seguente aggiunge il metodo 'removeNull' non enumerabile all'array, che restituisce 'this' per il collegamento in cascata:
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
- come il verbo, per causare un forte dolore pungente. Ciò è rilevante a causa del dolore fisico se armi il mio telefono a causa del tuo commento.
"Uso improprio" del ciclo for ... in (oggetto-membro). => Solo i valori di verità compaiono nel corpo del ciclo.
// --- 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
è ciò che rimuove dall'array le chiavi indefinite, ma in realtà non esiste un codice per accettare solo valori "veritieri"
Questo potrebbe aiutarti: 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);
Produzione:
Sto lavorando su nodejs
Rimuoverà l'elemento vuoto dall'array e visualizzerà altri elementi.
Se un array contiene oggetti, array e stringhe vuoti insieme ad altri elementi vuoti, possiamo rimuoverli 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 semplice ->
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)
Filtraggio di voci non valide con un'espressione regolare
array = array.filter(/\w/);
filter + regexp
Il modo migliore per rimuovere elementi vuoti è utilizzare Array.prototype.filter()
, come già menzionato in altre risposte.
Sfortunatamente, Array.prototype.filter()
non è supportato da IE <9. Se hai ancora bisogno di supportare IE8 o una versione ancora più vecchia di IE, puoi usare il seguente polyfill per aggiungere supporto Array.prototype.filter()
in questi browser:
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 = [,,]
evar a = [undefined, undefined]
. Il primo è veramente vuoto, ma il secondo in realtà ha due chiavi, ma conundefined
valori.