JavaScript中如何按数组属性对对象数组进行分组?
按属性分组JavaScript数组的实现方案
嘿,这个需求太常见了!我给你分享几个实用的实现方式,从原生JS到工具库的都有,你可以根据自己的场景选择:
1. 原生JS:用reduce实现(最推荐的原生方案)
reduce天生就是用来做这类聚合操作的,代码简洁且易读:
const arr = [ { id: 1 , name: "James"}, { id: 2, name: "John"}, { id: 1, name: "Jake"} ]; const groupedResult = arr.reduce((acc, currentItem) => { // 检查当前item的id是否已经在结果数组里有分组 const existingGroup = acc.find(group => group.id === currentItem.id); if (existingGroup) { // 有分组就把当前name追加进去 existingGroup.name.push(currentItem.name); } else { // 没有就新建一个分组项 acc.push({ id: currentItem.id, name: [currentItem.name] }); } return acc; }, []); // 初始值设为空数组,用来存放最终的分组结果 console.log(groupedResult); // 输出:[ { id: 1, name: ["James", "Jake"] }, { id: 2, name: ["John"] } ]
2. 原生JS:映射表优化方案(适合大数据量)
如果你的数组很大,上面的find方法每次遍历结果数组会有点性能损耗。这时候可以先用对象做映射(键查找是O(1)),最后再转成目标格式:
const arr = [ { id: 1 , name: "James"}, { id: 2, name: "John"}, { id: 1, name: "Jake"} ]; // 第一步:构建id到name数组的映射 const idToNamesMap = {}; arr.forEach(item => { // 如果当前id还没在映射里,就初始化一个空数组 if (!idToNamesMap[item.id]) { idToNamesMap[item.id] = []; } idToNamesMap[item.id].push(item.name); }); // 第二步:把映射对象转成目标格式的数组 const groupedResult = Object.entries(idToNamesMap).map(([idStr, names]) => ({ id: Number(idStr), // 对象的键是字符串,所以转成数字类型 name: names })); console.log(groupedResult); // 输出和上面一致
3. 工具库方案:用Lodash的groupBy(省心之选)
如果你的项目已经引入了Lodash,直接用现成的groupBy函数能省不少事:
const _ = require('lodash'); // 先确保项目里装了Lodash const arr = [ { id: 1 , name: "James"}, { id: 2, name: "John"}, { id: 1, name: "Jake"} ]; // 先按id分组,得到一个以id为键的对象 const groupedObj = _.groupBy(arr, 'id'); // 再把每个分组转成目标格式 const groupedResult = Object.values(groupedObj).map(group => ({ id: group[0].id, name: group.map(item => item.name) })); console.log(groupedResult);
内容的提问来源于stack exchange,提问作者BlueishVelvet
相关产品推荐
相关产品推荐

