How do I remove empty elements from an array in JavaScript?
Is there a straightforward way, or do I need to loop through it and remove them manually?
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]
or - Classic way: simple iteration
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
// [1,2,3,3,[],Object{},5,6]
var arr = [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,];
arr = $.grep(arr, n => n == 0 || n);
// [1, 2, 3, 3, 0, 4, 4, 5, 6]
[1,null,undefined,3,].filter(function(){;return true}) => [1, null, undefined, 3]filter calls a provided callback function once for each element in an array, and constructs a new array of all the values for which callback returns a true value.. and 'undefined' is not an empty value by the way, so as null.arr.filter(n => n) and its es5 equivalent will remove falsy values, which may not be desired. However filter, like other array methods, only iterates over defined values anyway. Thus filter(n => true) is a nice clean way to condense a sparse array.EDIT: This question was answered almost nine years ago when there were not many useful built-in methods in the Array.prototype.
Now, certainly, I would recommend you to use the filter method.
Take in mind that this method will return you a new array with the elements that pass the criteria of the callback function you provide to it.
For example, if you want to remove null or undefined values:
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);
It will depend on what you consider to be "empty" for example, if you were dealing with strings, the above function wouldn't remove elements that are an empty string.
One typical pattern that I see often used is to remove elements that are falsy, which include an empty string "", 0, NaN, null, undefined, and false.
You can pass to the filter method, the Boolean constructor function, or return the same element in the filter criteria function, for example:
var filtered = array.filter(Boolean);
Or
var filtered = array.filter(function(el) { return el; });
In both ways, this works because the filter method in the first case, calls the Boolean constructor as a function, converting the value, and in the second case, the filter method internally turns the return value of the callback implicitly to Boolean.
If you are working with sparse arrays, and you are trying to get rid of the "holes", you can use the filter method passing a callback that returns true, for example:
var sparseArray = [0, , , 1, , , , , 2, , , , 3],
cleanArray = sparseArray.filter(function () { return true });
console.log(cleanArray); // [ 0, 1, 2, 3 ]
Old answer: Don't do this!
I use this method, extending the native Array prototype:
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);
Or you can simply push the existing elements into other 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 call is really expensive on older browsers because they have to renumber all of the array keys to close up the gap.Array.prototype using Object.defineProperty to make the new function a non-enumerable property and then avoid the performance hit caused by putting .hasOwnProperty in every loop.If you need to remove ALL empty values ("", null, undefined and 0):
arr = arr.filter(function(e){return e});
To remove empty values and Line breaks:
arr = arr.filter(function(e){ return e.replace(/(\r\n|\n|\r)/gm,"")});
Example:
arr = ["hello",0,"",null,undefined,1,100," "]
arr.filter(function(e){return e});
Return:
["hello", 1, 100, " "]
UPDATE (based on Alnitak's comment)
In some situations you may want to keep "0" in the array and remove anything else (null, undefined and ""), this is one way:
arr.filter(function(e){ return e === 0 || e });
Return:
["hello", 0, 1, 100, " "]
function(e){return !!e}!!e will include NaN (unlike 0) whereous e would not (like 0).var myarr=[1, 2,, 3,, 3,undefined,,"",,0, 4,, 4,, 5,, 6,,,,].filter(Boolean); removes undefined,"" and 0Simply one liner:
[1, false, "", undefined, 2].filter(Boolean); // [1, 2]
or using underscorejs.org:
_.filter([1, false, "", undefined, 2], Boolean); // [1, 2]
// or even:
_.compact([1, false, "", undefined, 2]); // [1, 2]
Boolean works as a function...Boolean as a function it will simply return true or false wether the value is truly/falsy.(true).constructor === Boolean. And then tell me if we can do this with other build-ins in JS. ;)) (of course excluted the other 5 build-in constructors. (String, Array, Object, Function, Number))If you've got Javascript 1.6 or later you can use Array.filter using a trivial return true callback function, e.g.:
arr = arr.filter(function() { return true; });
since .filter automatically skips missing elements in the original array.
The MDN page linked above also contains a nice error-checking version of filter that can be used in JavaScript interpreters that don't support the official version.
Note that this will not remove null entries nor entries with an explicit undefined value, but the OP specifically requested "missing" entries.
undefined as its given value.For removing holes, you should use
arr.filter(() => true)
arr.flat(0) // New in ES2019
For removing hole, null, and, undefined:
arr.filter(x => x != null)
For removing hole, and, falsy (null, undefined, 0, -0, 0n, NaN, "", false, document.all) values:
arr.filter(x => x)
arr = [, null, (void 0), 0, -0, 0n, NaN, false, '', 42];
console.log(arr.filter(() => true)); // [null, (void 0), 0, -0, 0n, NaN, false, '', 42]
console.log(arr.filter(x => x != null)); // [0, -0, 0n, NaN, false, "", 42]
console.log(arr.filter(x => x)); // [42]
Note:
arr = [, ,];
console.log(arr[0], 0 in arr, arr.length); // undefined, false, 2; arr[0] is a hole
arr[42] = 42;
console.log(arr[10], 10 in arr, arr.length); // undefined, false, 43; arr[10] is a hole
arr1 = [1, 2, 3];
arr1[0] = (void 0);
console.log(arr1[0], 0 in arr1); // undefined, true; a[0] is undefined, not a hole
arr2 = [1, 2, 3];
delete arr2[0]; // NEVER do this please
console.log(arr2[0], 0 in arr2, arr2.length); // undefined, false; a[0] is a hole
arr = [1, 3, null, 4];
filtered = arr.filter(x => x != null);
console.log(filtered); // [1, 3, 4]
console.log(arr); // [1, 3, null, 4]; not modified
[, ,]arr.filter(x => x), JS will check whether x is truthy or falsy, i.e. if (x), therefore only the truthy value will be assigned to the new list.arr.flat() is my new favorite way of doing this.0 into flat. That's not documented on MDN and I didn't notice any effect. For others, here is the definition of sparse arraysThe clean way to do it.
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; this basically removes all falsy values.Actually, you can use ES6+ methods, assume the array is below:
const arr = [1,2,3,undefined,4,5,6,undefined,7,8,undefined,undefined,0,9];
And the answer could be one of these two ways:
First way:
const clearArray = arr.filter(i => i); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Second way:
const clearArray = arr.filter(Boolean); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Those two answers aren't utterly correct, even in the given example, yeah, it works but pay attention to the number 0 in the given array, by both ways number zero is disappeared and it's obviously related to checking items by using boolean coercion.
A completely correct way is to check nulish and remove them:
const notNil = (i) => !(typeof i === 'undefined' || i === null);
const clearArray = arr.filter(i => isNil(i));
const arr = [1,2,3,undefined,4,5,6,undefined,7,8,undefined,undefined,0,9];
const notNil = (i) => !(typeof i === 'undefined' || i === null);
console.log("Not nil: ", arr.filter(notNil));
arr.filter(i) => typeof i === 'number'; produce the same result?number? They could be anything, the primary purpose is to wipe all Nil things.With Underscore/Lodash:
General use case:
_.without(array, emptyVal, otherEmptyVal);
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
With empties:
_.without(['foo', 'bar', '', 'baz', '', '', 'foobar'], '');
--> ["foo", "bar", "baz", "foobar"]
compact is way better if you don't care about zeroesIf using a library is an option I know underscore.js has a function called compact() http://documentcloud.github.com/underscore/ it also has several other useful functions related to arrays and collections.
Here is an excerpt from their documentation:
_.compact(array)
Returns a copy of the array with all falsy values removed. In JavaScript, false, null, 0, "", undefined and NaN are all falsy.
_.compact([0, 1, false, 2, '', 3]);
=> [1, 2, 3]
@Alnitak
Actually Array.filter works on all browsers if you add some extra code. See below.
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"]
This is the code you need to add for IE, but filter and Functional programmingis worth is imo.
//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;
};
}
You may find it easier to loop over your array and build a new array out of the items you want to keep from the array than by trying to loop and splice as has been suggested, since modifying the length of the array while it is being looped over can introduce problems.
You could do something like this:
function removeFalsyElementsFromArray(someArray) {
var newArray = [];
for(var index = 0; index < someArray.length; index++) {
if(someArray[index]) {
newArray.push(someArray[index]);
}
}
return newArray;
}
Actually here is a more generic solution:
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]
You get the idea - you could then have other types of filter functions. Probably more than you need, but I was feeling generous... ;)
When using the highest voted answer above, first example, i was getting individual characters for string lengths greater than 1. Below is my solution for that problem.
var stringObject = ["", "some string yay", "", "", "Other string yay"];
stringObject = stringObject.filter(function(n){ return n.length > 0});
Instead of not returning if undefined, we return if length is greater than 0. Hope that helps somebody out there.
Returns
["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 Replacing that function... with String, ironically, leaves numbers in but would give the same result in your given array.I'm simply adding my voice to the above “call ES5's Array..filter() with a global constructor” golf-hack, but I suggest using Object instead of String, Boolean, or Number as suggested above.
Specifically, ES5's filter() already doesn't trigger for undefined elements within the array; so a function that universally returns true, which returns all elements filter() hits, will necessarily only return non-undefined elements:
> [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]
However, writing out ...(function(){return true;}) is longer than writing ...(Object); and the return-value of the Object constructor will be, under any circumstances, some sort of object. Unlike the primitive-boxing-constructors suggested above, no possible object-value is falsey, and thus in a boolean setting, Object is a short-hand for 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); is actually equivalent to someArray.filter(function(x){ return String(x); });. If you want to remove all falsy values someArray.filter(Boolean); works to remove 0, -0, NaN, false, '', null, and undefined.Object constructor as opposed to the return true method. @robocat the OP asked for empty elements to be removed, not nulls.var data = [null, 1,2,3];
var r = data.filter(function(i){ return i != null; })
console.log(r)
[1,2,3]
If an array contains empty Objects, Arrays, and Strings alongside other empty elements, we can remove them with:
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))
With 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)
With plain Javascript ->
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)
You can use filter with index and in operator
let a = [1,,2,,,3];
let b = a.filter((x,i)=> i in a);
console.log({a,b});
let a=[]; a.abc=1 - but usually no body do it (It is quite exotic to do it - because instead arrays you can just use e.g. object {}). And when you use array in so exotic way then standard JS array methods like map, filter etc. will ignore such key-value pairs - my solution based on filter and ignore it too. It is quite obvious that OP ask about standard JS array (because he not mention about such exotic use-case)in operator returned the value in the array. So I thought it would only work if the values in the array was the same as the index numbers one wanted to filter for. But I see now in refers to the properties (like indexes), not values, of an array..filter() will skip over empty slots in the array, so a.filter((x,i)=> i in a); will only check existing elements. And it's implicit that an existing element's index exists in the array. So, it simplifies to a.filter(() => true); few other answers here already show this approach.Another way to do it is to take advantage of the length property of the array : pack the non-null items on the 'left' of the array, then reduce the length. It is an in-place algorithm -does not allocates memory, too bad for the garbage collector-, and it has very good best/average/worst case behaviour.
This solution, compared to others here, is between 2 to 50 times faster on Chrome, and 5 to 50 times faster on Firefox, as you might see here : http://jsperf.com/remove-null-items-from-array
The code below adds the non-enumerable 'removeNull' method to the Array, which returns 'this' for daisy-chaining :
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--such as the verb, to cause a sharp stinging pain. This is relevant due to the physical pain if I weaponize my phone due to your comment.All the empty elements can be removed from an array by simply by using
array.filter(String);
It returns all non empty elements of an array in javascript
null while using Boolean removes it an empty strings.null and 0. Whichever way it's supposed to work it...doesn't. Especially if we consider anything that might have a custom toString() defined which can lead to further items considered falsy when they aren't.None of the answers above works best for all types. The below solution will remove null, undefined, {} [], NaN and will preserve date string and what's best is it removes even from nested objects.
function removeNil(obj) {
// recursively remove null and undefined from nested object too.
return JSON.parse(JSON.stringify(obj), (k,v) => {
if(v === null || v === '') return undefined;
// convert date string to date.
if (typeof v === "string" && /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ$/.test(v))
return new Date(v);
// remove empty array and object.
if(typeof v === 'object' && !Object.keys(v).length) return undefined;
return v;
});
}
function removeNil(obj) {
// recursively remove null and undefined from nested object too.
return JSON.parse(JSON.stringify(obj), (k,v) => {
if(v === null || v === '') return undefined;
// convert date string to date.
if (typeof v === "string" && /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ$/.test(v))
return new Date(v);
// remove empty array and object.
if(typeof v === 'object' && !Object.keys(v).length) return undefined;
return v;
});
}
const ob = {
s: 'a',
b: 43,
countries: [ 'a', 'b', 'c' ],
l: null,
n: { ks: 'a', efe: null, ce: '' },
d: new Date(),
nan: NaN,
k: undefined,
emptyO: {},
emptyArr: [],
}
const output = removeNil(ob);
console.log(output);
console.log('Tests: ', ob.countries.length, typeof(ob.d))
var a = [,,]andvar a = [undefined, undefined]. The former is truly empty, but the latter actually has two keys, but withundefinedvalues.null/undefinedin an array in this first place as much as you can. For instance, if yournulls come from mapping over another array with the map function returningnullfor certain elements, try toArray.filterout those elements prior to running the map. Makes your code more readable/self-documenting. Obviously, this doesn't work for every use case, but it can be applied to a lot.Array.filterdoes not help. See solution in the answer stackoverflow.com/questions/16196338/…