Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript iterating through sparse array

I have a sparse array (indexes are not consecutive) like this:

var testArray = { 0: "value1", 5: "value2", 10: "value3", 15: "value4" };

I would simply like to iterate through each item, do some stuff, and be able to break under a certain condition.

I am fairly new to Javascript and I didn't find a proper way to do it. Here is what I tried:

  1. Built-in "for..in". It seems that this is not the correct way to iterate through an array

  2. forEach from ECMASCRIPT5. This one iterate correctly, but I cannot break from the loop.

  3. _.each() from Underscore.js. Same result as #2.

  4. $.each() from JQuery. With this one I can break by returning false, but it won't iterate correctly. For the above example, instead of iterating at 0, 5, 10, 15, it will iterate at 0,1,2,3,4,5,6... which is obviously not what I expect.

So my question is: Is there an easy way to iterate a sparse array with the possibility to break during the loop in Javascript or would it be better to use another data structure like an hashtable? If so, any recommandation?

Thanks!

like image 785
Absolom Avatar asked May 13 '12 03:05

Absolom


5 Answers

What you have is not an array, it's just an object.

You can test by:

Array.isArray(testArray)

For what's worth, JavaScript does have array that's said to be sparse. This happens when you use delete operator to remove an element or change length property to larger.

To answer your question, to loop thru a object, best way is Object.keys(obj).forEach().

var o = {"a":3, "b":4};

Object.keys(o).forEach(
    function (key) {
        var val = o[key];
        console.log("Key:" + key);
        console.log("Value:" + val);
    }
);

The possible issue with for (var p in o) {…} is that it will also loop thru any enumerable properties in the parent (that is, the prototype chain). Usually it won't happen though, if you define you object by literal expression var obj = {...}, which by default its parent is Object.prototype, and it doesn't have any enumerable properties.

like image 93
Xah Lee Avatar answered Nov 17 '22 16:11

Xah Lee


What's wrong with the for...in syntax? You have an object so the for...in syntax is completely valid to use:

var testArray = { 0: "value1", 5: "value2", 10: "value3", 15: "value4" };

for (var key in testArray) {
  var value = testArray[key];

  if (...) {
    break;
  }
}
like image 10
Blender Avatar answered Nov 17 '22 15:11

Blender


For..in isn't the worst thing when you're working on an object hash. It's to be avoided for use with arrays ([]), but it should be ok here:

var val;
for (index in testArray) {
  if (index == 10) {
    break;
  } else {
    val = testArray[index];
  }
}
like image 3
rjz Avatar answered Nov 17 '22 16:11

rjz


First thing you have to kiss-bye-bye is "Array". There is no real Array in ECMAscript (forgetting about typed-arrays and binary trickery).

So what you've got there is a plain Object. To iterate over that, I'd suggest to use .forEach if you're cool with ES5. If you need to early break that iteration, you might want to use ES5 methods like .some() or .every(), like:

Object.keys( testArray ).some(function( key ) {
    if( +key < 15 ) {            
        return true;
    }

    console.log(key, testArray[key]);
});

This would interrup the iteration when a key is encountered which numerical value is not lower than 15, by returning true.

like image 2
jAndy Avatar answered Nov 17 '22 16:11

jAndy


You can also use (abuse) Array.every instead of Array.fromEach to break out of the loop early.

var pre = document.getElementById('console');

var arr = new Array();
arr[10] = 'Hello';
arr[20] = 'World!';
arr[30] = 'stop';
arr[40] = 'Goodbye';

arr.every(function (val, idx) {
  if (val !== 'stop') {
    pre.textContent += idx+': '+val+'\n';
    return true;
  }
});
<pre id="console"></pre>

Basically, Array.every immediately returns false as soon as one of its elements returns false. This lets you break out of the loop early.

like image 1
chowey Avatar answered Nov 17 '22 17:11

chowey