javascriptparent-childtraversal

Traversal with conditions


I am working with a hierarchical dataset traversing through all levels of children and transforming them based on some conditions. Once, I am done with the transformation, I need to store the transformed element in an array of objects for later use.

Following is an example of what I tried. But it is unable to push the transformation that is happening inside else {if (d.req === "y") block.

const data = [
    {
      name: "f1",req: "n",val: 0,
      children: [
        { name: "l1", req: "n", val: 1 },
        { name: "s1", req: "y", val: 2 },
        { name: "q1", req: "y", val: 3,
          children: [{ name: "i1" }, { name: "l1" }]
        }
      ]
    },
    { name: "d1", req: "n", val: 4, children: [{ name: "s1" }] }
  ];
  
  function traverse(data) {
    let container = [];

    data.forEach((d, i) => {
      if (d.req === "n") {
      
        //some external function
        //I want to push the result of external function to a container
        // for example
        
        container.push({ name: d.name, val: d.val * 100 });

        if (d.children) {
          traverse(d.children);

          d.children.forEach((d) => {
            if (d.req === "n") {
              container.push({ name: d.name, val: d.val * 100 });
            }
          });
        }
      } else {
        if (d.req === "y") {
        
          //some external function
          //I want to push the result of external function to a container
          // for example

          container.push({ name: d.name, val: d.val * -100 });

          if (d.children) {
            traverse(d.children);

            d.children.forEach((d) => {
              if (d.req === "y") {
                container.push({ name: d.name, val: d.val * -100 });
              }
            });
          }
        }
      }
    });
    return container;
  }
 console.log( traverse(data));

The desired final result is the following. I can't figure out what is wrong here.

[{
        "name": "f1",
        "val": 0
    },
    {
        "name": "l1",
        "val": 100
    },
    {
        "name": "d1",
        "val": 400
    },
    {
        "name": "s1",
        "val": -200
    },
    {
        "name": "q1",
        "val": -300
    }
]

Solution

  • You could push the results of the recursive calls.

    function traverse(data) {
        const 
            container = [],
            regs = { n: 100, y: -100 };
            
        data.forEach((d, i) => {
            if (d.req in regs) container.push({ name: d.name, val: d.val * regs[d.req] });
            container.push(...traverse(d.children || []));
        });
        
        return container;
    }
    
    const
        data = [{ name: "f1", req: "n", val: 0, children: [{ name: "l1", req: "n", val: 1 }, { name: "s1", req: "y", val: 2 }, { name: "q1", req: "y", val: 3, children: [{ name: "i1" }, { name: "l1" }] }] }, { name: "d1", req: "n", val: 4, children: [{ name: "s1" }] }];
    
    console.log(traverse(data));
    .as-console-wrapper { max-height: 100% !important; top: 0; }