I'm trying to understand the difference between an 'empty' sparse array (e.g. new Array(3)
) and an equivalent 'empty' dense array (array with 3 undefined entries).
I can create an array with 3 undefined values these two ways:
var sparse = new Array(3);
// or
var sparse = [,,,];
var dense = Array.apply(null, Array(3)); // See dense array link below
Dense Arrays
If I do console.log for either of these the result is:
[undefined, undefined, undefined]
If I loop over each array to compare it against the other one they will strictly match:
console.log(sparse.length === dense.length);
// true
for (var i = 0; i < dense.length; i++) {
console.log(i +':'+ (dense[i] === sparse[i]));
}
// '0:true'
// '1:true'
// '2:true'
However, if I use .forEach
(or map
, reduce
, etc) then the callback will never be called on the sparse array but will be called three times on the dense one:
sparse.forEach(function(val,i){
console.log(i +':'+ val);
});
// Nothing. No-op.
dense.forEach(function(val,i){
console.log(i +':'+ val);
});
// '0:undefined'
// '1:undefined'
// '2:undefined'
So my questions are:
- If they both have the same length, indexes, and values how is one iterable but the other isn't?
These functions are explicitly documented to perform this way. Both arrays are iteratable, but forEach
/map
/etc explicitly skips indices which are not in the array:
var sparse = new Array(3);
var dense = Array.apply(null, Array(3)); // See dense array link belo
1 in sparse; // false
1 in dense; // true
// Sparse can still be iterated over
sparse[100] = 'a'
sparse.forEach(function (n, i) { console.log(n, i) }); // a 100
- What is the reason for the difference?
Presumably an explicit decision was made to omit indices which don't exist
- What is the best way to determine if an array is sparse or dense?
You can use the following:
function isSparse(array) {
for (var i = 0; i < array.length; ++i) {
if (!i in array)
return true;
return false;
}
RE: Your comment
There has got be a reason for why [,,,] doesn't have indexes but [undefined, undefined, undefined] does.
There doesn't have to be a reason, that's just the way they're built. One has keys, the other doesn't.
Look:
Object.keys(Array(3)) // => []
Object.keys(['a','b']) // => ["0", "1"]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With