将数组中对象属性相同的放进同一个数组中生成一个二维数组,或者将相同的属性名创建为key,所有相同的对象为value生成一个对象。

2023新版本:可以根据第三个参数来控制生成二维数组还是对象

 /**
   * 根据数组中相同的属性名进行合并生成二维数组或者对象
   * 
   * @param {array} arrayList 要排序的数组
   * @param {string} propertyName 根据此属性名相同的进行合并
   * @param {string} outputType array|object array则生成二维数组,否则生成对象形式
   *
   */
  groupByProperty(arrayList, propertyName, outputType) {
    if (outputType === "array") {
      return Object.values(
        arrayList.reduce(function(result, obj) {
          let key = obj[propertyName];
          if (!result[key]) {
            result[key] = [];
          }
          result[key].push(obj);
          return result;
        }, {})
      );
    } else {
      return arrayList.reduce(function(result, obj) {
        let key = obj[propertyName];
        if (!result[key]) {
          result[key] = [];
        }
        result[key].push(obj);
        return result;
      }, {});
    }
  },

以下为原答案: 

项目中遇到一个需求,后端返回一个对象数组,要根据数组中的某个属性,相同的放进同一个数组中,生成一个二维数组来循环展示出来。

得到的是这样

我们要将这个数组中对象的name相同的放同一个数组中,现在网上能百度到的方法大多都是下面这个,而且也没有注释,变量名起的也看不太懂,我这里逐行注释一下。

/**
 * @param {array} arr 要排序的数组
 * @param {string} str 根据此属性名相同的进行合并
 *
*/
sortArr(arr, str) {
      var _arr = [],//二维数组
        _t = [],//str属性名相同的先放进这个临时数组
        _tmp;//临时属性名
      //先按照str排序,把相同str的放一起(关键步骤)
      arr.sort(function (a, b) {
        var s = a[str],
          t = b[str];
        return s > t ? -1 : 1;
      });
      if (arr.length) {
        //先取出数组中第一个str属性名存进 _tmp
        _tmp = arr[0][str];
      }
      for (var i in arr) {
        //如果和第一个存的属性名相同就push进临时数组中
        if (arr[i][str] === _tmp) {
           _t.push(arr[i]);
        } else {
          // 如果不同,拿到第一个不同的属性名赋值给 _tmp 临时属性名
          _tmp = arr[i][str];
          //把之前相同的放入最终的_arr
          _arr.push(_t);
          //把临时数组赋值为第一个不同的对象,(关键)否则下一次循环 i+1 就丢失一个对象
          _t = [arr[i]];
        }
      }
      //把最后一个集合放到_arr
      _arr.push(_t);
      return _arr;
    },

        这个方法也可以完成上边的需求,但是会有一个bug, 就是在第一步用.sort(),进行排序时,这个方法会先将属性名按照字符编码的顺序进行排序,这样就会打乱数组的顺序。举个例子:

我希望的name顺序是张三,李四,王五,a赵六。但是用Array.sort() ,排序后的输出是:

 可以看到a赵六这个名字跑到了最前边,就是因为 a 的字符编码比 张 的字符编码靠前。这就导致了经过Array.sort() ,排序后的数组会被不确定的打乱顺序。

所以这种方法并不符合我的需求,我们来看第二种方法:

/**
 * @param {array} arr 要排序的数组
 * @param {string} str 根据此属性名相同的进行合并
 *
*/
sortArr(arr, str) {
      var _arr = [] //最终的二维数组
      //取出所有要合并的属性名
      let strArr = arr.map(item=>{
        return item[str]
      })
      //对属性名进行一次去重
      strArr = Array.from(new Set(strArr)) 
      //先遍历属性名数组
      strArr.map(strItem =>{
        let temporaryArr = []
        //遍历所有的数组
        arr.forEach((objectItem)=>{
          //如果 strItem 和数组中的属性名相同就push进临时数组
          if(strItem == objectItem[str]){
            temporaryArr.push(objectItem)
          }
        })
        //在数组循环结束后,将临时数组push进二维数组中
        _arr.push(temporaryArr)
      })
      return _arr
},

这个的思路是

1.先拿到数组中所有的str,然后去重,得到一个属性名数组,
2.遍历arr根据相同的str,push进一个临时数组,
3.遍历开始时先将临时数组赋空,结束时将临时数组push进二维数组中。

这样就会根据属性名第一个出现的顺序来生成数组了,不会被打乱顺序。

第二种方法也可以在遍历所有数组的时候对数据进行一次简单的处理再push进数组中。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值