如何用JavaScript的reduce实现指定格式的数组分组?
当然可以用reduce实现,甚至有两种靠谱的方式!
首先,你的现有代码已经用reduce完成了分组到对象的步骤,其实只需要多一步把对象转换成你要的数组格式就行——这应该是最高效的方案,因为对象的键查找是O(1),比直接在数组里找分组快得多。
方案一:先分组到对象,再转成目标数组(推荐)
这是性能最优的方式,保留你原有的排序和reduce分组逻辑,最后用Object.entries()把对象键值对转成数组,再映射成需要的结构:
function groupByRange(products) { // 保持你的排序逻辑,确保同rangeCode的产品排在一起 products.sort((a, b) => a.rangeCode - b.rangeCode); // 用reduce生成分组对象,和你原来的写法一致 const groupedObj = products.reduce((accumulator, product) => { // 若当前rangeCode不存在则初始化数组,再push产品 (accumulator[product.rangeCode] = accumulator[product.rangeCode] || []).push(product); return accumulator; }, {}); // 将对象转换为目标数组格式 const groupedArray = Object.entries(groupedObj).map(([rangeCode, products]) => ({ rangeCode, products })); console.log(groupedArray); return groupedArray; }
方案二:直接用reduce生成目标数组
如果你想一步到位用reduce生成数组,也是可以的,不过这种方法因为每次要在数组中查找已有分组,数据量大时性能会差一点(时间复杂度O(n²)):
function groupByRange(products) { products.sort((a, b) => a.rangeCode - b.rangeCode); return products.reduce((accumulator, product) => { // 在累加器数组中查找是否已有当前rangeCode的分组 const existingGroup = accumulator.find(item => item.rangeCode === product.rangeCode); if (existingGroup) { // 已有分组,直接添加产品 existingGroup.products.push(product); } else { // 无分组,新增一个包含当前产品的分组项 accumulator.push({ rangeCode: product.rangeCode, products: [product] }); } return accumulator; }, []); // 这里累加器初始值是一个空数组,而不是空对象 }
关于reduce的小补充
其实reduce的核心就是累加器可以是任意类型——你之前用的是对象当累加器,现在方案二里用数组当累加器,只要每次返回更新后的累加器就行。如果数据量不大,两种写法都能用,但方案一的性能优势更明显,更推荐。
内容的提问来源于stack exchange,提问作者r3plica
相关产品推荐
相关产品推荐

