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

JS使用Map统计对象数组重复次数时无法识别重复值的问题

问题根因

JavaScript中对象属于引用类型,Map的键匹配规则采用SameValueZero相等判定:对于引用类型值,只有两个变量指向内存中同一个对象实例时,才会被判定为相等。
你数组中属性完全一致的重复书籍对象,本质是独立创建的不同实例,内存地址互不相同,因此每次执行mp.has(obj)都会返回false,最终所有条目计数都为1。
另外你的原代码存在一个隐性问题:for...of循环内的obj未做变量声明,会污染全局作用域,建议补充const声明。

可行解决方案

方案1:拼接业务唯一标识作为Map键(推荐,性能最优)

书籍的书名+作者组合可以作为唯一识别依据,将二者拼接为字符串作为Map的键,从根源上避免引用类型判断的问题。注意拼接时加入不会出现在书名/作者名中的特殊分隔符,避免不同字段拼接后产生歧义。

const mp = new Map()
for (const obj of collection) {
  // 用 || 作为分隔符,避免字段值拼接冲突
  const uniqueKey = `${obj.Title}||${obj.Author}`
  mp.set(uniqueKey, (mp.get(uniqueKey) || 0) + 1)
}

// 如果需要最终输出对象与计数的映射,可遍历Map做结构转换
const countList = []
for (const [key, count] of mp) {
  const [Title, Author] = key.split('||')
  countList.push({ book: { Title, Author }, count })
}

方案2:序列化对象作为键(适合属性固定的简单对象)

如果对象属性顺序固定、无循环引用、无函数/undefined等特殊值,可以直接用JSON.stringify将对象序列化为字符串作为键,代码更简洁:

const mp = new Map()
for (const obj of collection) {
  const key = JSON.stringify(obj)
  mp.set(key, (mp.get(key) || 0) + 1)
}

注意:如果两个对象属性顺序不同,哪怕属性值完全一致,JSON.stringify生成的字符串也会不同,会导致统计错误,使用前请确认数据源的对象属性顺序一致。

方案3:遍历对比属性(适合数据量小的场景)

如果不想生成额外的键,也可以在每次遍历的时候手动对比已统计对象的属性值,数据量较大时该方法性能较差,不推荐处理大体积txt解析后的数据集:

const countResult = []
for (const obj of collection) {
  const exist = countResult.find(item => 
    item.book.Title === obj.Title && item.book.Author === obj.Author
  )
  if (exist) {
    exist.count += 1
  } else {
    countResult.push({ book: obj, count: 1 })
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:31:11