I need to transform some data into a special format. The tricky part is, that it needs to be grouped and nested by dynamic keys. As the raw data is flat.
Here is some simplified example data:
const data = [
{
category: 'Classic',
price: 1,
order: '1233-ABC'
currency: 'EUR',
},
{
category: 'Classic',
price: 2,
order: '1234-ABC'
currency: 'EUR',
},
{
category: 'Modern',
price: 3,
order: '1235-ABC'
currency: 'USD',
},
{
category: 'Classic',
price: 4,
order: '1236-ABC'
currency: 'EUR',
},
{
category: 'Modern',
price: 5,
order: '1237-ABC'
currency: 'EUR',
},
{
category: 'Classic',
price: 6,
order: '1238-ABC'
currency: 'USD',
},
{
category: 'Modern',
price: 7,
order: '1239-ABC'
currency: 'USD',
}
];
Now I want to define the groupings and the aggregate.
For example:
grouping = ['category'];
sum = ['price'];
So it should groupBy the category
key and sum up all price
key entries.
// Expected Output
[{
category: 'Classic',
price: 13
}, {
category: 'Modern',
price: 15
}]
I got this working with reduce.
Here is the code:
let groupingsField = ['category'];
let aggregateField = ['price']
let [group, ...rest] = groupingsField
let [sum, ...noone] = aggregateField
const groupedData = data.reduce((acc, current) => {
acc.push({
[group]: current[group],
[sum]: data.filter(item => item[group] === current[group])
.map(el => el[sum])
.reduce((total, current) => total + current)
})
return acc
}, [])
.reduce((acc, current) => {
const x = acc.find(item => item[group] === current[group])
return !x ? acc.concat([current]) : acc
}, [])
However, I need the groupings to be dynamic and if more then 1 value is present there, it should create nested sub
data sets. It should be possible to add multiple groupings.
// Example 2
grouping = ['category', 'currency'];
sum = ['price'];
// Expected Output
[{
category: 'Classic',
price: 13,
sub: [{
currency: 'EUR',
price: 7
}, {
currency: 'USD',
price: 6
}]
}, {
category: 'Modern',
price: 15,
sub: [{
currency: 'EUR',
price: 9
}, {
currency: 'USD',
price: 10
}]
}]
Thus, if I would add another key to the grouping
grouping = ['category', 'currency', 'something'];
It should be three levels deep nestes.
{
category: 'Modern',
price: 15,
sub: [{
currency: 'EUR',
price: 9,
sub: [{
someting: ...
price: ...
}]
}]
}
However, I couldn't get my head around this, how to add the nesting dynamically based on the groupings
. I guess I need some recursion here.
Would love some help on this!