JavaScript数组合并相同属性对象并统计出现次数的实现问题
解决方案
核心问题在于JavaScript对象是引用类型,直接进行相等判断或作为Map键时,只会对比内存地址而非对象内部属性值,我们可以通过将对象的特征属性序列化为唯一标识字符串来解决这个问题。
实现代码
方案1:Map缓存实现
const data = [{a:1, b:2},{a:2, b:2},{a:2, b:2},{a:3, b:2},{a:3, b:2},{a:3, b:2}]; const countMap = new Map(); for (const item of data) { // 基于需要比对的属性生成唯一key const key = JSON.stringify({a: item.a, b: item.b}); if (countMap.has(key)) { // 已存在则计数+1 countMap.get(key).count++; } else { // 不存在则存入新对象,初始化count为1 countMap.set(key, {...item, count: 1}); } } // 提取Map的值即为最终结果 const result = Array.from(countMap.values()); console.log(result);
运行后输出结果和预期完全一致:[{a:1, b:2, count:1},{a:2, b:2, count:2},{a:3, b:2, count:3}]
方案2:reduce简化实现
如果偏好更简洁的写法,可以用数组reduce方法实现:
const data = [{a:1, b:2},{a:2, b:2},{a:2, b:2},{a:3, b:2},{a:3, b:2},{a:3, b:2}]; const result = Object.values(data.reduce((acc, cur) => { // 简单属性可以直接拼接生成key,不需要序列化 const key = `${cur.a}|${cur.b}`; acc[key] = acc[key] ? {...acc[key], count: acc[key].count + 1} : {...cur, count: 1}; return acc; }, {})); console.log(result);
注意事项
- 如果需要比对的属性顺序不固定,直接使用
JSON.stringify可能会因为属性排列顺序不同生成不同的key,这种场景可以先统一排序属性名再生成key,示例如下:
// 传入要比对的属性列表,排序后拼接生成稳定的唯一key const getUniqueKey = (obj, compareKeys = ['a', 'b']) => { return compareKeys.sort().map(key => `${key}:${obj[key]}`).join('||'); }
- 如果是多层嵌套的对象,也可以根据需求调整key的生成逻辑,支持深层属性的比对。
内容的提问来源于stack exchange,提问作者TinaSky
相关产品推荐
相关产品推荐

