Search code examples
javascriptarraystreenodes

Iteratively create layers of json


I have several arrays of strings that I want to generate a object out of. An example is this. Given I have:

let graph = {}
let a = ["Vehicle", "Car", "Sport"]
let b = ["Vehicle", "Car", "Van"]
let c = ["Vehicle", "Truck", "4x4"]

I want to make a function that I can pass a into and it would update graph to be:

{
    name: "Vehicle",
    children: [
        {
            name: "Car",
            children: [
                "Sport"
            ]
        }
    ]
}

I then pass b into the function and graph sees that "Vehicle" > "Car" already exists so it just pushes "Van" into the children. Then when c is passed it pushes a child onto the Vehicle children. I am having trouble as with a loop I am not able to account for the fact that the input can be of any length (not just 3). How can I loop through the depth of an object like this?


Solution

  • As I said in the comments box that, Your expected result isn't valid node tree, Because 3rd nested node should not contain array.

    Anyway Here is my answer:

    const nodes = new Map([["graph", { children: [], name: 'graph' }]]); // 'graph' is the root node 
    const entries = [["Vehicle", "Car", "Sport"], ["Vehicle", "Car", "Van"], ["Vehicle", "Truck", "4x4"]];
    
    function* createNodeIds(entrie, parentId, deep = 0) {
        const name = entrie.shift();
        const nodeId = parentId + '.' + name;
        yield [parentId, nodeId, name, ++deep];
        while (entrie.length)
            yield* createNodeIds(entrie, nodeId, deep);
    }
    
    for (const entrie of entries)
        for (const [parentId, nodeId, name, deep] of createNodeIds(entrie, 'graph'))
            if (!nodes.has(nodeId)) {
                const node = { name, children: [] }
                nodes.set(nodeId, node);
                nodes.get(parentId).children.push(deep > 2 ? name : node)
            }
    
    console.log(nodes.get('graph.Vehicle'));