数组聚合

363 阅读2分钟

需求

当我们有一个一维数组,我们希望把它按照某个类型聚合成二维数组;形如下面。

       // 原数组
        let arr = [{
                title: '一 1测试',
                id: 1
            },
            {
                title: '一 2测试',
                id: 1
            },
            {
                title: '一 3测试',
                id: 1
            },
            {
                title: '一 4测试',
                id: 1
            },
            {
                title: '二 1测试',
                id: 2
            },

        ]
        // 算法后的数组
        let newArr = [{
                "title": "一",
                "children": [{
                        "title": "一 1测试",
                        "id": 1
                    },
                    {
                        "title": "一 2测试",
                        "id": 1
                    },
                    {
                        "title": "一 3测试",
                        "id": 1
                    },
                    {
                        "title": "一 4测试",
                        "id": 1
                    }
                ]
            },
            {
                "title": "二",
                "children": [{
                    "title": "二 1测试",
                    "id": 2
                }]
            }
        ]

解答

方法一

      let map = {},
      dest = [];
    arr.forEach((item) => {
      // 不存在这个key,给dest 数组创建了一个项,并携带子集,并给map 创建了一项
      if (!map[item.id]) {
        dest.push({
          title: item.title,
          id: item.id,
          children: [item],
        });
        // 这个id已被标记
        map[item.id] = 'flag';
      }
      // 存在这个key,代表dest 已经有了这个值了,并且
      else {
        for (let j = 0; j < dest.length; j++) {
          let dj = dest[j];
          // 这个判断很重要,当前项已经在dest数组存在,所以要循环dest数组,找到匹配项,然后不找了
          if (item.id == dj.id) {
            dj.children.push(item);
            break;
          }
        }
      }
    });

方法二

let map = {},
      dest = [];
    arr.forEach((item) => {
      // 不存在这个key,给dest 数组创建了一个项,并携带子集,并给map 创建了一项
      if (!map[item.id]) {
        dest.push({
          title: item.title,
          id: item.id,
          children: [item],
        });
        // 这个id已被标记
        map[item.id] = 'flag';
      }
      // 存在这个key,代表dest 已经有了这个值了,并且
      else {
        let dj = dest.find(j => j.id == item.id)
        dj.children.push(item)
      }
    });
    console.log(dest);

方法三

            let map = {};
            let dest = arr.reduce((prev, next) => {
                let Key = next.id || "这个key值为null的情况";
                if (!map[Key]) {
                    prev.push({
                        title: next.title,
                        children: [next],
                    });
                    // 这个key已被标记
                    map[Key] = "flag";
                } else {
                    let dj = prev.find((j) => j.id == Key);
                    dj.children.push(next);
                }
                return prev;
            }, []);

思考:巧妙的地方在于利用对象只有唯一的key,来建立类型;一开始循环的时候,肯定没有任何类型,那么就创建一个类型,并且把这条数据放到新的数组中。第二次循环的时候,遇到了这个类型。那么去循环新的数组。通过类型比较,找到这个类型,然后在此类型的子集下添加当前项,跳出循环

对象的变量要用中括号很重要

递归

曾多次能看到敞开大门乘客们的科目曾多次

如果觉得好,就给点打赏吧,1元钱也行。

image.png