Home > Software design >  Recursively make a nested object given an array of objects and array of children?
Recursively make a nested object given an array of objects and array of children?

Time:01-24

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);

  • Related