如何在不改变原始源的情况下在嵌套对象数组中添加对象

how to add object in nested array of objects without mutating original source

我有多个对象嵌套数组,其中我需要根据 id 合并 grandChildren 中的对象而不进行突变

详情......

###示例

  let arr1 = {
  "initiateLevel": true,
  "parent": [
    {
      "name": "level1",
      "childrens": [
        {
          "group": "Level-group",
          "grandChildrens": [
            {
              "id": 21,
              "technology": "sp1",
              "path": "l2"
            },
            {
              "id": 22,
              "technology": "sp2",
              "path": "l2"
            }
          ]
        }
      ]
    },
    {
      "name": "level2",
      "childrens": [
        {
          "group": "Level-group-2",
          "grandChildrens": [
            {
              "id": 121,
              "technology": "sp12",
              "path": "l4"
            },
            {
              "id": 122,
              "technology": "sp22",
              "path": "l4"
            }
          ]
        }
      ]
    }
  ]
}

ex: below对象需要根据id合并到数组中

 let newobj=  
 [
      {
        "id": 22,
        "reason": "reason 2",
        "phase": "phase 2",
        "reviewer": "by user 2",
        "date": "date 2"
      },
      {
        "id": 21,
        "reason": "reason 1",
        "phase": "phase 1",
        "reviewer": "by user 1",
        "date": "date 1"
      }
    ]

expected output:

{
  "initiateLevel": true,
  "parent": [
    {
      "name": "level1",
      "childrens": [
        {
          "group": "Level-group",
          "grandChildrens": [
            {
              "id": 21,
              "technology": "sp1",
              "path": "l2",
              "reason": "reason 1",
              "phase": "phase 1",
              "reviewer": "by user 1",
              "date": "date 1"
            },
            {
              "id": 22,
              "technology": "sp2",
              "path": "l2",
              "reason": "reason 2",
              "phase": "phase 2",
              "reviewer": "by user 2",
              "date": "date 2"
            }
          ]
        }
      ]
    },
    {
      "name": "level2",
      "childrens": [
        {
          "group": "Level-group-2",
          "grandChildrens": [
            {
              "id": 121,
              "technology": "sp12",
              "path": "l4"
            },
            {
              "id": 122,
              "technology": "sp22",
              "path": "l4"
            }
          ]
        }
      ]
    }
  ]
}

我试着喜欢这个。但它不起作用

const merge = (y, z) => {
  y.parent.forEach((element) => {
    element.childrens.forEach((x) => {
      x.grandChildrens.forEach((test) => {
        const reviewIndex = z.findIndex(
          (reviewItem) => reviewItem.id === test.id
        );
        if(reviewIndex>=0)
        {
         return  {...test, ...z[reviewIndex]}  
        }
        
      });
    });
  });
};

merge(arr1,newobj)

如何根据id合并对象不突变

改用Array.prototype.mapforEach没有returns

let newobj = [
  {
    id: 22,
    reason: 'reason 2',
    phase: 'phase 2',
    reviewer: 'by user 2',
    date: 'date 2'
  },
  {
    id: 21,
    reason: 'reason 1',
    phase: 'phase 1',
    reviewer: 'by user 1',
    date: 'date 1'
  }
];

let arr1 = {
  initiateLevel: true,
  parent: [
    {
      name: 'level1',
      childrens: [
        {
          group: 'Level-group',
          grandChildrens: [
            {
              id: 21,
              technology: 'sp1',
              path: 'l2',
              reason: 'reason 1',
              phase: 'phase 1',
              reviewer: 'by user 1',
              date: 'date 1'
            },
            {
              id: 22,
              technology: 'sp2',
              path: 'l2',
              reason: 'reason 2',
              phase: 'phase 2',
              reviewer: 'by user 2',
              date: 'date 2'
            }
          ]
        }
      ]
    },
    {
      name: 'level2',
      childrens: [
        {
          group: 'Level-group-2',
          grandChildrens: [
            {
              id: 121,
              technology: 'sp12',
              path: 'l4'
            },
            {
              id: 122,
              technology: 'sp22',
              path: 'l4'
            }
          ]
        }
      ]
    }
  ]
};

const merge = (y, z) => {
  const parent = y.parent.map((element) => {
    return { 
      ...element, 
      childrens: element.childrens.map((x) => {
        return {
          ...x,
          grandChildrens: x.grandChildrens.map((test) => {
            return { ...test, ...z.find((reviewItem) => reviewItem.id === test.id) };
           })
         };
       })
     }
  });
  return { ...y, parent }; 
};

const arr2 = merge(arr1, newobj);
console.log(arr2);