I am trying to create a nested object recursively. Here is the sample data:
"reactions": [
{
"name": "Ester amidation",
"target": "Data #1",
"sources": ["Data #2", "Data #3"],
},
{
"name": "Buchwald-Hartwig amination with amide",
"target": "Data #4",
"sources": ["Data #5", "Data #1"], // BECAUSE Data #1 is a target AND in sources for Data #4, we should nest it as a child of Data #4
}
]
Given the target
, I was trying to have something that will output something like:
{
name: "My Route 1",
children: [
{
name: "Data #4",
children: [
{
name: "Data #5",
children: []
},
{
name: "Data #1",
children: [
{
name: "Data #2",
children: []
},
{
name: "Data #3",
children: []
}
]
},
],
},
],
};
I have tried something like this but I get confused when it comes to handling arrays:
function createNestedTree(objects, target = null) {
const children = objects.filter(o => o.target === target);
if (!children.length) {
return null;
}
return children.map(child => ({
...child,
children: createNestedTree(objects, child.id)
}));
}
Anyone have an idea of how to create an algorithm for this? Much appreciated!
CodePudding user response:
You could first iterate the data to create the target objects (with empty children
arrays), and reference them in a Map keyed by name. Then iterate the data to populate those children
arrays, and at the same time mark children as not being a root. Return the remaining root(s).
Here is a possible implementation:
function makeTree(reactions) {
const map = new Map(reactions.flatMap(({target, sources}) =>
[target, ...sources].map(name => [name, { name, children: [] }])
));
const roots = new Map(map);
for (const {target, sources} of reactions) {
for (const source of sources) {
map.get(target).children.push(map.get(source));
roots.delete(source);
}
}
return [...roots.values()];
}
const reactions = [{"name": "Ester amidation","target": "Data #1","sources": ["Data #2", "Data #3"],},{"name": "Buchwald-Hartwig amination with amide","target": "Data #4","sources": ["Data #5", "Data #1"]}];
const result = makeTree(reactions);
console.log(result);