Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

While Loop with Array.pop() Gotcha

LEGEND ,
Jun 05, 2010 Jun 05, 2010

Just a bit of a heads up:

A number of us have been using a while(obj=array.pop()){} construct for a while. (I believe Marc was the one to introduce this construct to this forum.)

While this is considerably more efficient than a standard for loop when you don't need the array when the loop ois done, there's a not-so-obvious gotcha:

0 in javascript is evaluated to false, so : while(0) is equivalent to while(false).

If you have an loop like this:

ar = [1,0,8,6];
while(a=ar.pop()){
    // do your stuff
    }

6 and 8 will resolve true, but 0 will not. The loop will exit when it hits 0, and neither 0 nor 1 will be processed.

This loop is no good either:

ar = [1,0,8,6];
while(a=ar.pop() != null){
    //do your stuff
    }

because "a" will evaluate to either true or false instead of the value of the array because statements are processed backwards (i.e. a = (ar.pop != null)).

Instead you need (note the extra parenthesis):

ar = [1,0,8,6];
while((a=ar.pop()) != null){
    //do your stuff
    }

HTH,

Harbs

TOPICS
Scripting
13.8K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 06, 2010 Jun 06, 2010

Actually, even the last construct is not  safe. If there's a null object in the array it'll exit prematurely as well.

For null objects, this will work:

ar = [1,null,8,6];
while((a=ar.pop()) !== undefined){
    //do your stuff
}

But if you have a non-consecutive array this too will fall flat on its face:

ar = [1,null,8,6];
ar[6] = 2;
while((a=ar.pop()) !== undefined){
    //this will only process 2
}

Bottom line, don't use the pop() as the condition of the loop. Do something like this instead:

ar = [1,null,8,6];

ar[6] = 2;
while(ar.length){
    a=ar.pop();
    // now we can process all elements of the array!
}

Harbs

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jun 07, 2010 Jun 07, 2010

Good point, Harbs 😉

That's why I wouldn't recommand using the while( a=ar.pop() ){...} pattern on simple one-dimensional arrays that contain, or could contain primitive types. As a general rule I use this tip on temporary arrays of objects, or on n-dimensional temporary arrays, because I am absolutely sure that none of the elements can be evaluated to false. Then it is a useful shortcut. In other situations the old good index loop is the best although it requires an additional variable.

@+

Marc

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 07, 2010 Jun 07, 2010
LATEST

Hi Marc,

I wasn't blaming you for my mistakes! I just got bitten by using this technique for primitive type arrays, and I figured I should prevent others from making my mistake...

But even for primitive arrays, while(array.length)array.pop() is more efficient than a for loop.

Harbs

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines