Here's a solution that uses no external libraries:
/**
* Add the given object to the given set.
*
* @param {object} theSet The set to add this object to.
* @param {object} theObject The object to add to the set.
*
* @return {object} theSet, with theObject added to it.
*
* @note Assumes that theObject.name should be the key,
* while theObject.id should go into the value array.
* @note This is an Array.prototype.reduce() callback.
*/
function collect(theSet, theObject) {
if (theSet.hasOwnProperty(theObject.name)) {
theSet[theObject.name].push(theObject.id);
} else {
theSet[theObject.name] = [theObject.id];
}
return theSet;
}
var names = [{name:"high",id:5},{name:"high",id:6},
{name:"low",id:1}, {name:"low",id:2},{name:"medium",id:3},{name:"medium",id:4}],
combinedSet = names.reduce(collect, {}), // This is Step 1
final = [],
key;
// This is Step 2
for (key in combinedSet) {
if (combinedSet.hasOwnProperty(key)) {
final.push(
{
"name" : key,
"items": combinedSet[key]
}
);
}
}
The first step is to group the IDs under the object names. I use Array.prototype.reduce to do this, with the callback collect. The result of that transformation goes into the combinedSet variable.
The second step is to take the set we made in Step 1 and turn it into the final array: make objects using the set's keys as the name member, and use its values as the items member. I can't use reduce like I could before, so I go with a simple for loop. Note that I wrapped things up with a hasOwnProperty check, to guard against the possibility that someone has modified Object.prototype; if I didn't do this, then there might be more items in the set that I hadn't put there, and that would introduce bugs.