Javascript: How to clear undefined values from an array
Asked Answered
W

14

6

I'm trying to loop through an array and delete and skip the elements until only one is existing. i've tried splicing but it messes up my loop because the element from arr[1] then becomes arr[0] etc.

Let's say there are 10 people. I'd like to remove person 1 then keep person 2 then remove person 3 and keep person 4. This pattern will go on until only one is left.

any kind of help will do.

Weiss answered 7/3, 2012 at 5:4 Comment(4)
What do you mean "until only one is left"? After one pass through the array you'll have cut it from 10 to 5 elements (people) - are you saying you want to keep repeating that process (with repeated passes through) until the array has only one element in it?Macready
If you want only one element... Then why do you need a loop?Showily
@MathWizz, that was my thinking as well, the position of the remaining element can be calculated without the need for looping.Lambeth
Yes I will be repeating the process until there is only one left.Weiss
S
9

you should not change the collection during the iterating, not just JavaScript but all language, define a new array and add those ones you want to delete in it, and iterate that one later to delete from first one.

Stereoscope answered 7/3, 2012 at 5:8 Comment(5)
You can change it, if you control the index. However, this is less error prone than my suggestionAmiraamis
How about adding the ones you want to keep to the second array, then at the end replace the first array with the second? Saves having to iterate through a second time.Macready
My opinion is just we should try to keep our code simple and easy to read, my expedience just tell me that writing a strange complex loop can only bring bugs and confuse othersStereoscope
I misread Simon's suggestion, the real easy way to do it is what nnnnnn suggested (under this answer), copy it to a new arrayAmiraamis
I ended up using 3 arrays, first as the original which is the basis for the loop. within the loop 2 arrays are used. the second array contains those that are skipped in that iteration and another is an empty array. at the end of each iteration, i do this. arr1 = arr2; arr2 = arr3; I'm not sure if this is the best solution but it made sense like what Simon said to make it simpler and it worked.Weiss
C
29

Filter the falsy items:

var a=[1,2,"b",0,{},"",NaN,3,undefined,null,5];
var b=a.filter(Boolean); // [1,2,"b",{},3,5]
Cassidy answered 15/12, 2014 at 14:48 Comment(2)
@Cassidy Best one i've seen so far. I usually check against undefineds or trueA
alexoviedo999 Wow! Thanks!Ist
A
9

When you splice, just decrement your loop index.

There were lots of good suggestions, I'll post the code for the different options and you can decide which to use

Decrement index when splicing http://jsfiddle.net/mendesjuan/aFvVh/

var undef;
var arr = [1,2, undef, 3, 4, undef];
for (var i=0; i < arr.length; i++) {
    if ( arr[i] === undef ) {
        arr.splice(i,1);
        i--;
    }
}

Loop backwards http://jsfiddle.net/mendesjuan/aFvVh/1/

var undef;
var arr = [1,2, undef, 3, 4, undef];
for (var i=arr.length - 1; i >=0; i--) {
    if ( arr[i] === undef ) {
        arr.splice(i,1);
    }
}

Copy to new array http://jsfiddle.net/mendesjuan/aFvVh/2/

var undef;
var arr = [1,2, undef, 3, 4, undef];
var temp = [];
for (var i=0; i < arr.length; i++) {
    if ( arr[i] !== undef ) {
        temp.push(arr[i])
    }
}
arr = temp;

Use filter which is just a fancy way to create a new array

var undef;
var arr = [1,2, undef, 3, 4, undef];
arr = arr.filter(function(item){
    return item !== undef;
});

At the end of all those examples, arr will be [1,2,3,4]

Performance

IE 11, FF and Chrome agree that Array.splice is the fastest. 10 times (Chrome), 20 times (IE 11) as fast as Array.filter. Putting items into a new array was also slow when compared to Array.slice. See http://jsperf.com/clean-undefined-values-from-array2

I am really surprised to see IE lead the pack here, and to see Chrome behind FF and IE. I don't think I've ever run a test with that result.

Amiraamis answered 7/3, 2012 at 5:7 Comment(0)
S
9

you should not change the collection during the iterating, not just JavaScript but all language, define a new array and add those ones you want to delete in it, and iterate that one later to delete from first one.

Stereoscope answered 7/3, 2012 at 5:8 Comment(5)
You can change it, if you control the index. However, this is less error prone than my suggestionAmiraamis
How about adding the ones you want to keep to the second array, then at the end replace the first array with the second? Saves having to iterate through a second time.Macready
My opinion is just we should try to keep our code simple and easy to read, my expedience just tell me that writing a strange complex loop can only bring bugs and confuse othersStereoscope
I misread Simon's suggestion, the real easy way to do it is what nnnnnn suggested (under this answer), copy it to a new arrayAmiraamis
I ended up using 3 arrays, first as the original which is the basis for the loop. within the loop 2 arrays are used. the second array contains those that are skipped in that iteration and another is an empty array. at the end of each iteration, i do this. arr1 = arr2; arr2 = arr3; I'm not sure if this is the best solution but it made sense like what Simon said to make it simpler and it worked.Weiss
P
3

If by any chance you're using CoffeeScript then to remove undefined from Array do this

values = ['one', undefined]
values = (item for item in values when item != undefined) 

values
/* => ['one'] */
Pacifistic answered 12/12, 2012 at 17:10 Comment(0)
M
2

Loop backwards. (Removing items will thus not affect the indexes of elements not yet processed.)

Macready answered 7/3, 2012 at 5:10 Comment(0)
F
1

Surprisingly, nobody have answered the best and correct way:

  1. Create new array
  2. Iterate on the old array and only push the elements you want to keep to the new array

some credit goes to @nnnnnn comment

Frenum answered 7/3, 2012 at 5:4 Comment(1)
It's fairly slow when compared to using splice jsperf.com/clean-undefined-values-from-array2/2Amiraamis
A
0

Not gathering exactly what you are trying to achieve, but I feel you are relying on the position index of an item in the array to continue with your program. I would in this case suggest a hashed array, i.e., a Key<>Value pair array.

In which case, arr["2"] always points at the item you had placed in it originally. Thus you can logically/numerically loop through, while not worrying about changes in position.

Beware of the Type Conversion risk and pitfalls!

Appointed answered 7/3, 2012 at 5:11 Comment(0)
T
0

Your best bet is to create a duplicate of the array, then splice from the original.

Or just go using a collection (key->value) and just delete the key eg

 People = {a: "Person A", b: "Person B", c:"Person C"};
 delete People.a;
 delete People.c;  //now the People collection only has 1 entry.

You can replace a,b,c with numbers just using it as an example,

 People = {0: "Person A", 1: "Person B", 2:"Person C"};
 delete People[0];
 delete People[1];
Tammeratammi answered 7/3, 2012 at 5:11 Comment(2)
You missed the point, OP knows to splice, the problem is that the index is stale after removing an itemAmiraamis
@Juan Mendes, Better off using key->value collections instead thenTammeratammi
S
0
function removeUndefined(array)
{
    var i = 0;
    while (i < array.length)
        if (typeof array[i] === 'undefined')
            array.splice(i, i);
        else
            i++;
    return array;
}

EDIT: I wrote this based on the title. Looks like the question asks something completely different.

Showily answered 7/3, 2012 at 5:15 Comment(3)
if array[i] is empty or false or 0 it will be also deleted.Gastric
I think you meant .splice(i, 1)Macready
@Gastric I've fixed that.Showily
G
0

this is a sample for you

<script lanauge = "javascript">
    var arr = ["1","2","3","4"];
    delete arr[1];// arr[1] is undefined
    delete arr[2];// arr[2] is undefined

    // now arr.length is 4

    var todelete = [];
    for (i = 0 ; i < arr.length ;i++)
    {
        if (typeof arr[i] == 'undefined') todelete.push(i);
    }

    todelete.sort(function(a, b) { return b-a }); // make the indeies from big to small

    for (i = 0;i < todelete.length; i ++)
    {
        arr.splice(todelete[i],1);
    }

    // now arr.length is 2

</script>
Gastric answered 7/3, 2012 at 5:26 Comment(1)
That .sort() method isn't doing what the comment says it is. Without a callback function it will do an ascending lexicographic sort.Macready
L
0

This may not be what you want, but you can easily calculate what the final element at the end of this procedure will be, then just grab it. Assuming that the elements of the array are contiguous and start at arr[0], you can find:

var logBase2OfLength = Math.floor(Math.log(arr.length) / Math.log(2));
var finalElement = arr[(1 << logBase2OfLength) - 1];

Basically, if you take the integer power of 2 that is less than or equal to the number of elements in your array, that is the position of the element that will remain after all of the looping and deleting.

Lambeth answered 7/3, 2012 at 5:56 Comment(0)
H
0
>If you are getting undefined during deletion of the key-pair, Then to prevent "undefined" you can try code given below to delete key-pair  


   1) test = ["1","2","3","4",""," "];
   2) var delete = JSON.stringify(test);   
      case1) delete = delete.replace(/\,""/g,'');  
         or  
      case2) delete = delete.replace(/\," "/g,'');  
         or  
      case3) delete = delete.replace(/\,null/g,'');  

   3) var result = JSON.parse(delete);  
Headmistress answered 17/3, 2018 at 20:39 Comment(0)
H
0

simply [NaN, undefined, null, 0, 1, 2, 2000, Infinity].filter(Boolean)

Hoofbound answered 2/2, 2023 at 10:0 Comment(0)
I
-1
  while(yourarray.length>1) //only one left
    {
    // your code
    }
Iveyivie answered 7/3, 2012 at 5:10 Comment(1)
length is a property of the array, not a function.Silvan

© 2022 - 2024 — McMap. All rights reserved.