代码小技巧:数组分组实现方式

假设我们有一个数组,数组如下:

const people = [
    {name: 'one', age: 30, sex: '男', address: {province: "浙江", city: "杭州"}},
    {name: 'two', age: 23, sex: '男', address: {province: "浙江", city: "杭州"}},
    {name: 'three', age: 30, sex: '女', address: {province: "浙江", city: "杭州"}},
    {name: 'four', age: 23, sex: '男', address: {province: "福建", city: "厦门"}},
    {name: 'five', age: 23, sex: '女', address: {province: "福建", city: "龙岩"}},
    {name: 'six', age: 24, sex: '男', address: {province: "福建", city: "龙岩"}},
];

我们有一个需求,需要按name属性进行分组,我们可以按如下实现:

const result = {};
for (let item of people) {
    let key = item.age;
    if (!result[key]) {
        result[key] = []
    }
    result[key].push(item);
}
console.log(result);

此时result打印出了我们要的结果

{
  '23': [
    { name: 'two', age: 23, sex: '男' },
    { name: 'four', age: 23, sex: '男' },
    { name: 'five', age: 23, sex: '女' }
  ],
  '24': [ { name: 'six', age: 24, sex: '男', address: {} } ],
  '30': [
    { name: 'one', age: 30, sex: '男' },
    { name: 'three', age: 30, sex: '女' }
  ]
}

但是需求是会变化的,有一天我们想按sex属性分组,上面的代码就不能够满足需求了。我们发现当我们想按sex属性分组时,只需要将上面代码的age改为sex就可以

const result = {};
for (let item of people) {
  	//此处是变化的
    let key = item.sex;
    if (!result[key]) {
        result[key] = []
    }
    result[key].push(item);
}
console.log(result);

我们很容易发现代码只有key是不同的,所以我们可以想到封装一个函数,我们叫这个函数为groupBy

function groupBy(arr, propName) {
    const result = {};
    for (let item of arr) {
        let key = item[propName];
        if (!result[key]) {
            result[key] = []
        }
        result[key].push(item);
    }
    return result;
}

console.log(groupBy(people, 'age'));
console.log(groupBy(people, 'sex'));

分组其实还有很多情况:

  1. 按嵌套的字段分组
  2. 按组合字段分组,比如:age+sex
  3. 直接按数组元素的奇偶进行分组

可以看到,当加入上述情况后,上面的函数就嘎了。需求本质上是key在变化,所以怎么获得key才是问题的关键,将上述函数修改

function groupBy(arr, generateKey) {
    const result = {};
    for (let item of arr) {
      //变化的
        let key = generateKey(item);
        if (!result[key]) {
            result[key] = []
        }
        result[key].push(item);
    }
    return result;
}

// 按年龄
console.log(groupBy(people, (item) => item.age));
// 按性别
console.log(groupBy(people, (item) => item.sex));
// 按年龄和性别组合
console.log(groupBy(people, (item) => `${item.sex}-${item.age}`));
// 按嵌套字段
console.log(groupBy(people, (item) => item.address.province));

const arr = [1, 2, 3, 4, 5, 6]
console.log(groupBy(arr, (item) => item % 2 === 0 ? '偶' : '奇'))

我们将获取key的方式通过函数传入,解决了我们的问题。然而这种方式调用起来不太方便,我们希望函数可以有有两种调用方式:groupBy(people, (item) => item.age)或者groupBy(people, 'age'),这时候我们就可以对参数进行判断:

function groupBy(arr, generateKey) {
    if (typeof generateKey === 'string') {
        const propName = generateKey;
        generateKey = (item) => item[propName];
    }
    const result = {};
    for (let item of arr) {
        let key = generateKey(item);
        if (!result[key]) {
            result[key] = []
        }
        result[key].push(item);
    }
    return result;
}

通过判断generateKey传入的类型对参数进行处理转化就可以实现不同的调用方式。

原文链接:https://juejin.cn/post/7226933918830051385 作者:一介散修

(0)
上一篇 2023年4月29日 上午10:43
下一篇 2023年4月29日 上午10:53

相关推荐

发表回复

登录后才能评论