I created a function that can group an array by one or more properties:
var groupBy = function (fields, data) {
var groups = {};
for (var i = 0; i < data.length; i++) {
var item = data[i];
var container = groups;
for (var j = 0; j < fields.length; j++) {
var groupField = fields[j];
var groupName = item[groupField];
if (!container[groupName]) {
container[groupName] = j < fields.length - 1 ? {} : [];
}
container = container[groupName];
}
container.push(item);
}
return groups;
};
For instance, when I use this sample input
var animals = [
{type: "cat", name: "Max"},
{type: "dog", name: "Charlie"},
{type: "cat", name: "Zoe"},
{type: "dog", name: "Abby"},
{type: "cat", name: "Molly"}
];
var groupedAnimals = groupBy(["type"], animals);
The output looks like:
{
"cat": [
{
"type": "cat",
"name": "Max"
},
{
"type": "cat",
"name": "Zoe"
},
{
"type": "cat",
"name": "Molly"
}
],
"dog": [
{
"type": "dog",
"name": "Charlie"
},
{
"type": "dog",
"name": "Abby"
}
]
}
Everything is functioning correctly so far...but the issue arises when I need the keys to mirror the original order of the input-array. Since JS objects do not guarantee order, how can I ensure the correct order?
Update:
It seems like the desired result should be:
groupBy(["type", "name"], animals)
which would result in:
[
{
"group": "cat",
"items": [
{
"group": "max",
"items": [
{
"type": "cat",
"name": "Max"
}
]
},
{
"group": "Zoe",
"items": [
{
"type": "cat",
"name": "Zoe"
}
]
},
{
"group": "Molly",
"items": [
{
"type": "cat",
"name": "Molly"
}
]
}
]
},
{
"group": "dog",
"items": [
{
"group": "Charlie",
"items": [
{
"type": "dog",
"name": "Charlie"
}
]
},
{
"group": "Abby",
"items": [
{
"type": "dog",
"name": "Abby"
}
]
}
]
}
]