ChenKuan1110 / blog

MIT License
0 stars 0 forks source link

组数分组的一些🤔️ #2

Open ChenKuan1110 opened 12 months ago

ChenKuan1110 commented 12 months ago

现有如下一些用户数据,需要对如下数据按照某一属性进行分组

const people = [
  { name: 'Alice', age: 30, sex: 'female'},
  { name: 'Bob', age: 25, sex: 'male'},
  { name: 'Charlie', age: 30, sex: 'male'},
  { name: 'Diana', age: 25, sex: 'female'},
  { name: 'Eva', age: 25, sex: 'female'},
  { name: 'Frank', age: 25, sex: 'male'},
  { name: 'Grace', age: 20, sex: 'female'},
]

例如: 按照年龄进行分组,那么可以这样实现

const result = {}
for (p of sourceArr) {
const key = p.age
if(!result[key]){
   result[key] = []
 }
 result[key].push(p)
}
console.log(result)

如果需要按照性别进行分组,那个只需要将上述代码中的 const key = p.age 替换为 p.sex就可以实现对性别的的分组

同样的,如果需要同时对年龄和性别进行分组,那个也只需要修改上述 key 的生成逻辑,例如: key = ${p.age}-${p.sex}

ChenKuan1110 commented 12 months ago

既然可以这样实现,那就抽离一个公用的方法吧

function groupBy (sourceArr, prop) {
  const result = {}
  for (item of sourceArr) {
    const key = item[prop]
    if(!result[key]){
      result[key] = []
    }
    result[key].push(item)
  }
  return result
}
ChenKuan1110 commented 12 months ago

针对第二个参数(分组条件的属性值),可以通过传递一个函数,用于生成用于分组的属性值

function groupBy (sourceArr, generateKey) {
  const result = {}
  for (item of sourceArr) {
    const key = generateKey(item)
    if(!result[key]){
      result[key] = []
    }
    result[key].push(item)
  }
  return result
}

调用的时候,通过 groupBy(people, item => item.age)实现对年龄的分组, 通过 groupBy(people, item => `${item.age}-${item.sex}`)实现对年龄和性别的分组

ChenKuan1110 commented 12 months ago

对第二个参数利用 "参数归一化" 处理一下,使之能够即处理接收普通字符串,也支持接收回调函数的方式

function groupBy (sourceArr, generateKey) {
  // 参数归一化,如果传递过来的是普通字符串,生成一个获取该字符串属性的方法
  if (typeof generateKey === 'string') {
    const propName = generateKey
    generateKey = (item) => item[propName] 
  }
  const result = {}
  for (item of sourceArr) {
    const key = generateKey(item)
    if(!result[key]){
      result[key] = []
    }
    result[key].push(item)
  }
  return result
}

调用方式: groupBy(people, 'age') groupBy(people, 'sex') groupBy(people, item => `${item.age}-${item.sex}`)