javascript 将线性数组的对象与嵌套数组的对象合并

irlmq6kh  于 2023-05-05  发布在  Java
关注(0)|答案(1)|浏览(273)

我有两个包含对象的数组A和B。A是我预先存在的数组,B是我用来改变A的数组。
以下是我将B合并到A的要求:
如果A中存在B的成员,我需要用B对象替换A对象,但保留A对象的所有属性,用B对象的属性覆盖任何匹配的属性。
如果A中不存在B成员,我需要将其添加到数组中,使其成为A中第一个对象的兄弟对象。
下面是我的两个数组,A和B:

let a = [
  {
    "key": "parent-1",
    "type": "parent",
    "items": [
      {
        "key": "parent-1-1",
        "type": "parent",
        "items": [
          {
              "key": "child-1-1",
              "dataType": "text",
              "description": "foo",
              "someproperty": "stays"
          }
        ]
      },
      {
        "key": "parent-1-2",
        "type": "parent",
        "items": [
          {
            "key": "child-1-2",
            "dataType": "text"
          }
        ]
      }
    ]   
  }
]

let b = [
  {
      "key": "child-1-1",
      "dataType": "text",
      "description": "bar"
  },
  {
      "key": "child-2",
      "dataType": "text",
      "description": "Since this does not appear in A it should be inserted as a next sibling to first array element (parent-1)"
  }
]

下面是我目前合并数组的方法:

const c = [
  ...a.filter(i => !b.some(j => j.key===i.key)),
  ...b.map(i => ({...a.find(j => j.key===i.key) ?? {}, ...i}))
]
console.log(c)

我的问题是,我上面的方法只适用于线性对象,当对象有子对象时就会崩溃。我需要修改我的方法来处理复杂的对象。我在寻找更好的方法。
以下是我试图实现的预期结果:

c = [
    {
    "key": "parent-1",
    "type": "parent",
    "items": [
        {
        "key": "parent-1-1",
        "type": "parent",
        "items": [
            {
                "key": "child-1-1",
                "dataType": "text",
                "description": "bar",
                "someproperty": "stays"
            }
        ]
        },
        {
        "key": "parent-1-2",
        "type": "parent",
        "items": [
            {
            "key": "child-1-2",
            "dataType": "text"
            }
        ]
        }
    ]   
    },
    {
        "key": "child-2",
        "dataType": "text",
        "description": "Since this does not appear in A it goes as sibling to  first el: parent-1"
    }
]
mctunoxg

mctunoxg1#

不是一个花哨的方法,但一个经典的递归应该可以工作:

let a = [{
  "key": "parent-1",
  "type": "parent",
  "items": [{
      "key": "parent-1-1",
      "type": "parent",
      "items": [{
        "key": "child-1-1",
        "dataType": "text",
        "description": "foo",
        "someproperty": "stays"
      }]
    },
    {
      "key": "parent-1-2",
      "type": "parent",
      "items": [{
        "key": "child-1-2",
        "dataType": "text"
      }]
    }
  ]
}]

let b = [{
    "key": "child-1-1",
    "dataType": "text",
    "description": "bar"
  },
  {
    "key": "child-2",
    "dataType": "text",
    "description": "Since this does not appear in A it should be inserted as a next sibling to first array element (parent-1)"
  }
]

function traverse(arr, bElm) {
  if (arr.length === 0) {
    return false
  }

  let isFound = false

  arr.forEach((arrElm, idx, originalArray) => {
    if (arrElm.key === bElm.key) {
      originalArray[idx] = {
        ...originalArray[idx],
        ...bElm,
      }

      isFound = true
    }

    if ('items' in arrElm) {
      let result = traverse(arrElm.items, bElm)

      isFound = result || isFound
    }
  })

  return isFound
}

b.forEach(bElm => {
  let result = traverse(a, bElm)

  if (!result) {
    a.push(bElm)
  }
})

console.log(a)

相关问题