user16860065
user16860065

Reputation:

Update an deeply nested array of objects based on an object : Javascript

I am having an deeply nested array of objects with certain properties, and given an object as input, it should update that object along with its children recursively. The format it has is as follows,

const arr = [
  {
    name: "parent",
    children: [
      {
        name: "child1",
        children: [
          {
            name: "granchild1",
            children: [],
            class: "level-2 leaf",
            config: {
              name: "granchild1",
              value1: false,
              value2: false
            }
          }
        ],
        class: "level-1 leaf",
        config: {
          name: "child1",
          value1: false,
          value2: false
        }
      },
      {
        name: "child2",
        children: [],
        class: "level-1 leaf",
        config: {
          name: "child2",
          value1: false,
          value2: false
        }
      }
    ],
    class: "level-0 group",
    config: {
      name: "parent",
      value1: false,
      value2: false
    }
  }
];

The given input object will look like

const obj = {
  name: "parent",
  value1: true,
  value2: true
};

Given this input, the object with matching name should update it's and children's value1 and value2 with the obj's values

Output should look like

const result = [
  {
    name: "parent",
    children: [
      {
        name: "child1",
        children: [
          {
            name: "granchild1",
            children: [],
            class: "level-2 leaf",
            config: {
              name: "granchild1",
              value1: true,
              value2: true
            }
          }
        ],
        class: "level-1 leaf",
        config: {
          name: "child1",
          value1: true,
          value2: true
        }
      },
      {
        name: "child2",
        children: [],
        class: "level-1 leaf",
        config: {
          name: "child2",
          value1: true,
          value2: true
        }
      }
    ],
    class: "level-0 group",
    config: {
      name: "parent",
      value1: true,
      value2: true
    }
  }
];

Code that I tried. How do I achieve the same output

const res = arr.map((item) => {
  let foundItem = arr.find((item) => item.name === obj.name);
  return {
    ...foundItem,
    children: {
      value1: obj.value1,
      value2: obj.value2
    }
  };
});

Upvotes: 0

Views: 1729

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370669

You need a recursive function that passes along whether the desired parent was found in one of its ancestors.

const arr=[{name:"parent",children:[{name:"child1",children:[{name:"granchild1",children:[],class:"level-2 leaf",config:{name:"granchild1",value1:!1,value2:!1}}],class:"level-1 leaf",config:{name:"child1",value1:!1,value2:!1}},{name:"child2",children:[],class:"level-1 leaf",config:{name:"child2",value1:!1,value2:!1}}],class:"level-0 group",config:{name:"parent",value1:!1,value2:!1}}];

const recurse = (arr, nameToFind, objToMerge, inAncestor = false) => {
  return arr.map(obj => {
    const mergeThis = inAncestor || obj.name === nameToFind;
    const merged = !mergeThis ? obj : { ...obj, config: { ...obj.config, ...objToMerge } };
    if (merged.children) {
      merged.children = recurse(merged.children, nameToFind, objToMerge, mergeThis);
    }
    return merged;
  });
};
const obj = {
  name: "parent",
  value1: true,
  value2: true
};
const { name, ...objToMerge } = obj;
const result = recurse(arr, name, objToMerge);
console.log(result);

Upvotes: 1

Related Questions