You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于指定函数对数组分组?求JS链式调用实现代码逐步骤详解

数组分组函数逻辑逐步骤解析

先给出原函数代码:

const group_By = (arr, fn) =>
  arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
    acc[val] = (acc[val] || []).concat(arr[i]);
    return acc;
  }, {});

函数基础说明

该函数接收两个参数:

  • arr:待分组的原始数组
  • fn:分组规则,支持两种传入形式:
    • 自定义函数:返回值作为每个元素的分组key
    • 字符串:指定原始数组元素的属性名,用该属性值作为分组key

链式调用分步拆解

整个函数的逻辑分为map生成分组key、reduce聚合分组两个阶段,链式调用依次执行:

阶段1:map生成所有元素的分组key

arr.map(typeof fn === 'function' ? fn : val => val[fn])
这段是map方法的回调逻辑,通过三元表达式适配两种分组规则:

  • 如果传入的fn是函数,直接用该函数处理数组的每个元素,得到对应分组key
  • 如果传入的fn不是函数(通常为属性名字符串),自动生成回调函数,取每个元素对应属性的值作为分组key

示例:若原始数组为[{category:'a', id:1}, {category:'b', id:2}],传入fn = 'category'时,该阶段返回结果为['a', 'b']。

阶段2:reduce完成分组聚合

map执行完返回的key数组,直接调用reduce做聚合,reduce初始值为空对象{},回调的三个参数分别是:

  • acc:累加器,存储当前已经生成的分组结果
  • val:当前遍历到的分组key(即上一步map的返回值元素)
  • i:当前遍历的索引值,对应原始数组的元素索引

每一轮遍历的执行逻辑:

  1. 先判断累加器中是否存在当前key对应的分组:acc[val] || [],若不存在则默认赋值空数组
  2. 将原始数组对应索引的元素arr[i]追加到该分组数组中,concat方法会返回新数组,直接赋值给acc[val]
  3. 返回累加器进入下一轮遍历

完整运行示例

// 测试数据
const goods = [
  {type: 'fruit', name: 'apple'},
  {type: 'vegetable', name: 'carrot'},
  {type: 'fruit', name: 'banana'},
]
// 调用函数,按type属性分组
const result = group_By(goods, 'type');

执行过程:

  1. map阶段返回key数组:['fruit', 'vegetable', 'fruit']
  2. reduce初始值为{}
    • 第1轮:key为fruit,原数组索引0的元素是苹果,累加器新增fruit属性,值为[{type: 'fruit', name: 'apple'}]
    • 第2轮:key为vegetable,原数组索引1的元素是胡萝卜,累加器新增vegetable属性,值为[{type: 'vegetable', name: 'carrot'}]
    • 第3轮:key为fruit,原数组索引2的元素是香蕉,追加到已有的fruit分组数组中
  3. 最终返回的分组结果:
{
  fruit: [ {type: 'fruit', name: 'apple'}, {type: 'fruit', name: 'banana'} ],
  vegetable: [ {type: 'vegetable', name: 'carrot'} ]
}

内容的提问来源于stack exchange,提问作者Mrblue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:15:01