js - Array - arrayDeepMerge

js - Array - arrayDeepMerge

需求

数组深度合并

      var arr1 = [
        {
          name: '正卷',
          id: '1',
          Children: [
            {
              name: '目录1',
              id: '1-1',
              Children: [
                {
                  name: '第1页',
                  id: '1-1-1'
                },
                {
                  name: '第2页',
                  id: '1-1-2'
                },
                {
                  name: '第3页',
                  id: '1-1-3'
                }
              ]
            },
            {
              name: '目录2',
              id: '1-2',
              Children: [
                {
                  name: '第1页',
                  id: '1-2-1'
                },
                {
                  name: '第2页',
                  id: '1-2-2'
                },
                {
                  name: '第3页',
                  id: '1-2-3'
                }
              ]
            }
          ]
        }
      ]
      var arr2 = [
        {
          name: '正卷',
          id: '1',
          Children: [
            {
              name: '123',
              id: '1-1',
              Children: [
                {
                  name: '第1页',
                  id: '1-1-1'
                },
                {
                  name: '第2页',
                  id: '1-1-2'
                },
                {
                  name: '第4页',
                  id: '1-1-4'
                }
              ]
            }
          ]
        },
        {
          name: '副卷',
          id: '2',
          Children: [
            {
              name: '123',
              id: '2-1',
              Children: [
                {
                  name: '第1页',
                  id: '2-1-1'
                },
                {
                  name: '第2页',
                  id: '2-1-2'
                },
                {
                  name: '第3页',
                  id: '2-1-3'
                }
              ]
            }
          ]
        }
      ]

期望结果

[
  {
    "name": "正卷",
    "id": "1",
    "Children": [
      {
        "name": "123",
        "id": "1-1",
        "Children": [
          {
            "name": "第1页",
            "id": "1-1-1"
          },
          {
            "name": "第2页",
            "id": "1-1-2"
          },
          {
            "name": "第3页",
            "id": "1-1-3"
          },
          {
            "name": "第4页",
            "id": "1-1-4"
          }
        ]
      },
      {
        "name": "目录2",
        "id": "1-2",
        "Children": [
          {
            "name": "第1页",
            "id": "1-2-1"
          },
          {
            "name": "第2页",
            "id": "1-2-2"
          },
          {
            "name": "第3页",
            "id": "1-2-3"
          }
        ]
      }
    ]
  },
  {
    "name": "副卷",
    "id": "2",
    "Children": [
      {
        "name": "123",
        "id": "2-1",
        "Children": [
          {
            "name": "第1页",
            "id": "2-1-1"
          },
          {
            "name": "第2页",
            "id": "2-1-2"
          },
          {
            "name": "第3页",
            "id": "2-1-3"
          }
        ]
      }
    ]
  }
]

utils

      /**
       * @method 数组深度合并
       * @description 数组深度合并
       * @param arr1
       * @param arr2
       * @param key 判断相同字段 默认id
       * @param childsKey 子数组字段 默认childs
       * @return
       */
      function arrayDeepMerge(arr1, arr2, key = 'id', childsKey = 'childs') {
        let resArray = [],
          concatArray = arr1.concat(arr2)
        concatArray.forEach(v => {
          // resArray 中不存在此key 表示未合并,进行合并
          if (!resArray.some(v1 => v1[key] == v[key])) {
            let targetObjs = concatArray.filter(v1 => v1[key] == v[key])
            if (targetObjs.length == 1) {
              // 此key在arr1,arr1不冲突,不需要merge,push即可
              resArray.push(v)
            } else {
              // 此key在arr1,arr1冲突,需要merge
              let [obj1, obj2] = targetObjs
              resArray.push(
                Object.assign(
                  {},
                  obj1,
                  obj2,
                  // 存在子数组 递归子数组合并
                  obj1[childsKey]?.length || obj2[childsKey]?.length
                    ? {
                        [childsKey]: arrayDeepMerge(obj1[childsKey] || [], obj2[childsKey] || [], key, childsKey)
                      }
                    : {}
                )
              )
            }
          }
          // resArray 中存在此key 表示已合并,不需要操作
        })
        return resArray
      }

demo

<!--
 * @createDate: 2022-07-23 15:17:11
 * @Author: zclee
 * @LastEditTime: 2022-07-23 16:13:27
 * @LastEditors: zclee
 * @FilePath: \lee-vue-press\cnblog\js - Array - arrayDeepMerge.html
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      var arr1 = [
        {
          name: '正卷',
          id: '1',
          Children: [
            {
              name: '目录1',
              id: '1-1',
              Children: [
                {
                  name: '第1页',
                  id: '1-1-1'
                },
                {
                  name: '第2页',
                  id: '1-1-2'
                },
                {
                  name: '第3页',
                  id: '1-1-3'
                }
              ]
            },
            {
              name: '目录2',
              id: '1-2',
              Children: [
                {
                  name: '第1页',
                  id: '1-2-1'
                },
                {
                  name: '第2页',
                  id: '1-2-2'
                },
                {
                  name: '第3页',
                  id: '1-2-3'
                }
              ]
            }
          ]
        }
      ]
      var arr2 = [
        {
          name: '正卷',
          id: '1',
          Children: [
            {
              name: '123',
              id: '1-1',
              Children: [
                {
                  name: '第1页',
                  id: '1-1-1'
                },
                {
                  name: '第2页',
                  id: '1-1-2'
                },
                {
                  name: '第4页',
                  id: '1-1-4'
                }
              ]
            }
          ]
        },
        {
          name: '副卷',
          id: '2',
          Children: [
            {
              name: '123',
              id: '2-1',
              Children: [
                {
                  name: '第1页',
                  id: '2-1-1'
                },
                {
                  name: '第2页',
                  id: '2-1-2'
                },
                {
                  name: '第3页',
                  id: '2-1-3'
                }
              ]
            }
          ]
        }
      ]
      /**
       * @method 数组深度合并
       * @description 数组深度合并
       * @param arr1
       * @param arr2
       * @param key 判断相同字段 默认id
       * @param childsKey 子数组字段 默认childs
       * @return
       */
      function arrayDeepMerge(arr1, arr2, key = 'id', childsKey = 'childs') {
        let resArray = [],
          concatArray = arr1.concat(arr2)
        concatArray.forEach(v => {
          // resArray 中不存在此key 表示未合并,进行合并
          if (!resArray.some(v1 => v1[key] == v[key])) {
            let targetObjs = concatArray.filter(v1 => v1[key] == v[key])
            if (targetObjs.length == 1) {
              // 此key在arr1,arr1不冲突,不需要merge,push即可
              resArray.push(v)
            } else {
              // 此key在arr1,arr1冲突,需要merge
              let [obj1, obj2] = targetObjs
              resArray.push(
                Object.assign(
                  {},
                  obj1,
                  obj2,
                  // 存在子数组 递归子数组合并
                  obj1[childsKey]?.length || obj2[childsKey]?.length
                    ? {
                        [childsKey]: arrayDeepMerge(obj1[childsKey] || [], obj2[childsKey] || [], key, childsKey)
                      }
                    : {}
                )
              )
            }
          }
          // resArray 中存在此key 表示已合并,不需要操作
        })
        return resArray
      }
      let res = arrayDeepMerge(arr1, arr2, 'id', 'Children')
      console.log(JSON.stringify(res, null, 2))
      // console.log(res)
    </script>
  </body>
</html>

posted @ 2022-07-23 16:49  zc-lee  阅读(43)  评论(0编辑  收藏  举报