I have fairly symmetrical data I want to reduce:
const data = [
{
name: 'Bob',
relations: {
siblings: [
{
name: 'Tom',
age: '20'
snacks: [
{
type: 'yogurt'
}
]
},
{
name: 'Jacob'
snacks: [
{
type: 'cookie',
amount: '2'
}
{
type: 'brownie',
amount: '3'
}
]
}
]
}
},
{
name: 'Robert',
relations: {
siblings: [
{
name: 'Timmy',
age: '16'
snacks: [
{
type: 'fudge'
}
{
type: 'brownie'
}
]
}
]
}
}
];
What I’m trying to produce:
const output = {
name: ['Bob', 'Robert'],
relations: {
siblings: {
name: ['Tom', 'Jacob', 'Timmy'],
age: ['20', '16'],
snacks: {
type: ['yogurt', 'cookie', 'fudge', 'brownie'],
amount: ['2', '3']
}
}
}
}
I understand how to do this without recursion, but I wanted a solution that would go deep.
Usually I just use reduce with recursion, but then I realized that I would have to add the value to the current level of the object which I don’t know how to do.
const compact = (value) => {
if (typeof value === 'string') {
return { [value]: '' }; // turning into an object for the mean time
}
if (Array.isArray(object)) { }
// if object
return Object.entries(object).reduce((accum, [key, value]) => {
// Do I have to pass accum[key] into compact here? Is this the correct way to do this?
accum[key] = compact(value);
return accum;
}, {});
};
2
Answers
By having only fixed properties like
relations.siblings
, you could take a dynamic approach and hand over only the target for getting a flat structure.Here is what I would propose: divide functionality into two different functions; one for summerizing a given object, and another for merging two objects that are already summerized.
Then it could be like this: