6

I'm trying to loop through a sparse array and fill in sparse elements with a value.

['foo', 'bar', , , ,].map(el => el || 'default') // returns ["foo", "bar", undefined × 3]

How would I return ["foo", "bar", "default", "default", "default", "default"]

9
  • 2
    From mdn "map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values." Commented Jan 27, 2016 at 22:03
  • @pawel - Although the callback is not called for those indexes, the return value from map() still has those positions. Commented Jan 27, 2016 at 22:08
  • @TedHopp it does, but they're unchanged, which rather defeats the point for the OP Commented Jan 27, 2016 at 22:11
  • @TedHopp yes, because the callback hasn't been called. I'm not sure I get your point. Commented Jan 27, 2016 at 22:16
  • 1
    If it matters, just set the array length explicitly to the desired size, rather than relying on the (slightly odd) behaviour of the array literal syntax. Commented Jan 27, 2016 at 23:00

2 Answers 2

5

Since .map (and also .forEach) will skip sparse values there's no option except to use a loop, but you should explicitly check for the absence of the missing keys

for (var i = 0, n = a.length; i < n; ++i) {
    if (!(i in a)) {       // explicit check for missing sparse value
        a[i] = "default";
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

This will be short one default, but I don't think there's any way around that.
To @RickHitchcock point, it appears that all of these answers will be short one default.
@RickHitchcock ah, didn't spot the OP has one more default than element entries - perhaps that was a mistake?
He may think that the last comma creates a new undefined element, which would not be the case.
Correct. If an array ends with a comma, the final comma is ignored. See jsfiddle.net/mm5utmwh for a simple example.
|
2

This should do it:

function Fill(n, _default) {
  return Array.apply(null,n).map(function(val) {
    return val || _default;
  });
}
var newa = Fill(myarray, "default");
console.log(JSON.stringify(newa));

Shown working here:

var myarray = ['foo', , 'bar', , , , ];
function Fill(n, _default) {
  return Array.apply(null, n).map(function(val) {
    console.log("val:" + val);
    return val || _default;
  });
}
var newa = Fill(myarray, "default");
console.log(JSON.stringify(newa));

6 Comments

@Alnitak Are you sure? Try Array.apply( null, [, , ,]).map( i => typeof i ), should return [ "undefined", "undefined", "undefined" ].
ok, this works, but it's kinda kludgy, since it replaces the implicit undefined sparse entries with explicit undefined entries, and then replaces any falsey value found.
@pawel I deleted that comment when I realised my test was wrong
The "falsey" value can be modified in the return statement as needed; but this does use the map :) however ugly
@MarkSchultheiss it does, but it doesn't permit (should it matter) any distinction between a truly missing (sparse) value and an existing value of undefined.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.