In ECMA5 you could do it like this
Javascript
function createFilledArray(obj) {
return Object.keys(obj).reduce(function(acc, key) {
var repeat = obj[key],
count;
for(count = 0; count < repeat; count += 1) {
acc.push(key);
}
return acc;
}, []);
}
var a = {
'a': 5,
'b': 1,
'c': 3
};
console.log(createFilledArray(a));
On jsFiddle
Which in terms of underscore would look like this
Javascript
function createFilledArray(obj) {
return _.reduce(_.keys(obj), function(acc, key) {
var repeat = obj[key],
count;
for(count = 0; count < repeat; count += 1) {
acc.push(key);
}
return acc;
}, []);
}
On jsFiddle
Which if you wanted to go further and replace the for
Javascript
function createFilledArray(obj) {
return _.reduce(_.keys(obj), function(acc, key) {
_.times(obj[key], function() {
acc.push(key);
});
return acc;
}, []);
}
On jsFiddle
And now for a little interest factor, lets have a look at the performances of the above 3 functions as we introduce more of Underscores methods, and we'll also compare them against the accepted solution by @mrhobo
Here is the jsPerf
Something else that none of these take into account, and it is unclear from your question, is whether alphabetical order is a must. If it is then a sort will need to be thrown into the mix, as none of these guarantee the ordering.
Finally, in ES3 as mentioned in the comments.
Javascript
function createFilledArray(obj) {
var acc = [],
key,
repeat,
count;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
for (count = 0, repeat = obj[key]; count < repeat; count += 1) {
acc.push(key);
}
}
}
return acc;
}
On jsFiddle
I have added the ES3 method to the jsPerf also.
And if you want to chain the result with other Underscore methods.
_.chain(createFilledArray(a)).forEach(function(element) {
console.log(element);
});
[{a}, {a}, {a}, {a}, {a}, {b}, {c}, {c}, {c}]?[a, a, a, a, a, b, c, c, c]is actually an array of strings, not objects?forloop, but you just add more overhead. Depends on what you want.