views:

8039

answers:

10

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?

Thanks

A: 

You'll need use some form of iteration to accomplish this. There isn't any built in mechanism in JavaScript to accomplish the task.

Matty
+1  A: 

You'll have to loop and then splice()

Kon
+2  A: 

Try this. Pass it your array and it will return with empty elements removed. *Updated to address the bug pointed out by Jason

function removeEmptyElem(ary) {
    for (var i=ary.length;i>=0;i--) {
        if (ary[i] == undefined)  {
            ary.splice(i, 1);
        }    
    }
    return ary;
}
Matty
DON'T use this function, it fails for obvious reasons: Try it on this array: var myArray = [1,2,,3,,3,,,,,,4,,4,,5,,6,,,,];
Jason Bunting
Oh yes it is somewhat buggy. If you fix it I will accept your answer.
DrJokepu
This has been updated and should no longer experience the same error
Matty
The iteration start with i=ary.length which is wrong. It should be i=ary.length-1
GetFree
+4  A: 

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... ;)

Jason Bunting
+12  A: 

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:

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,,,,]);
CMS
Could clone it and return that instead...
neonski
Jason Bunting
Yes the second method, but the first one you pass the value of the elements that you want to delete [null,,,0,,0,0,0,false,null,0].clean(null) == [0,0,0,0,false,0]
CMS
I realize that - which is why I only spoke of the second option. As for the first one, it is so narrow in scope that I would hesitate to make it part of the Array's prototype. See Alnitak's answer on this page for something that would be more ideal. Yours does allow for chaining though, obviously.
Jason Bunting
Your first solution is really nice if you don't have access to the "filter" method. Else I believe Alnitak's answer is better.
Joe Pineda
And what has the best performance? 1) or 2) approach? (or something like jQuery.grep() / Array.filter )
AlfaTeK
+9  A: 

If you've got Javascript 1.6 or later you can use Array.filter using a function similar to the isNullOrUndefined function in Jason's answer. See:

https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter

This page also contains a nice error-checking version of filter that can be used in JavaScript interpreters that don't support the official version.

Alnitak
You're right! It can be so simple as this (and works!):test3 = [1,2,,3,,3,,,,7,,,7,,,0,,,4,,4,,5,,6,,undefined,,null,,];printp( "Using array's native filtering: ", test3.filter( function(value){return (value==undefined) ? 0 : 1;} ) );
Joe Pineda
Yeah, it works - but not all browsers have JavaScript 1.6, so it's only that good.
Jason Bunting
+1 As Alnitak said, they have the code that can be used in the case of not having js 1.6 available
Sameer Alibhai
+1  A: 

This works, I tested it in AppJet (you can copy-paste the code on its IDE and press "reload" to see it work, don't need to create an 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]
*/
Joe Pineda
+3  A: 

@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;
  };
}
Erik Johansson
yes, that's exactly what I said in my answer.
Alnitak
A: 

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

lcabral
+4  A: 

Pure javascript:

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

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

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


via jQuery:

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

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

arr // [1, 2, 3, 3, 4, 4, 5, 6]
vsync
note - filter was introduced in javascript 1.6
vsync