假设我们有一个数组,数组如下:
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'));
分组其实还有很多情况:
- 按嵌套的字段分组
- 按组合字段分组,比如:age+sex
- 直接按数组元素的奇偶进行分组
可以看到,当加入上述情况后,上面的函数就嘎了。需求本质上是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 作者:一介散修