I am trying to transform a JSON file that comes from an API with a structure similar to this:
{
"fruitType": {"name": "bananas"},
"plantedIn": {"country": "USA", "state": "Minnesota"},
"harvestMethod": {"name": "manual"},
"product": {"id": "841023781723"},
},
... (other fruits, or the same fruit planted/harvested differently)
Into something like this:
"bananas": {
"USA": {
"manual": {
"841023781723": {
"fruitType": {"name": "bananas"},
"plantedIn": {"country": "USA", "state": "Minnesota"},
"harvestMethod": {"name": "manual"},
"product": {"id": "841023781723"},
}
}
}
},
...
So, essentially I want to group first by fruitType name
, then by plantedIn country
, then by harvestMethod name
, and finally product id
.
After some research I found that lodash
is popular for this kind of grouping. I developed a very naive solution with their chain
, groupBy
and mapValues
methods like so:
const _ = require('lodash');
const groupedData = _.chain(data)
.groupBy('fruitType.name')
.mapValues(values => _.chain(values)
.groupBy('plantedIn.country')
.mapValues(values => _.chain(values)
.groupBy('harvestMethod.name')
.mapValues(values => _.chain(values)
.groupBy('product.id')
.value()
).value()
).value()
).value()
This solution, however functional, feels very verbose and is likely inefficient. Therefore I would like to ask if there is any better alternative, either with loadash or any other way.
You could take an array of function to get the keys and build the structure.
const
data = [{ fruitType: { name: "bananas" }, plantedIn: { country: "USA", state: "Minnesota" }, harvestMethod: { name: "manual" }, product: { id: "841023781723" } }],
keys = [o => o.fruitType.name, o => o.plantedIn.country, o => o.harvestMethod.name, o => o.product.id],
result = data.reduce((r, o) => {
keys.reduce(
(q, fn, i, { length }) => q[fn(o)] ??= i + 1 === length ? o : {},
r
);
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }