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

如何高效深度对比数组内对象并找出完全重复项?

数组深度对比查找完全重复对象的高效方案

针对你提到的数百个对象的场景,哈希法是可靠且性能最优的选择,同时也有其他可行方案,以下是具体分析和实现:

哈希对比法(首推)

可靠性说明

只要保证对象序列化的稳定性(相同结构和值的对象生成完全一致的字符串),哈希法可以100%准确识别重复对象——SHA-1/MD5等算法的碰撞概率极低,完全可以忽略普通业务场景下的碰撞风险。如果极端担心碰撞,可以在哈希冲突时额外用深度对比做校验(几乎不会触发)。

实现步骤

  1. 生成稳定序列化字符串
    原生JSON.stringify不保证对象键的顺序,会导致相同对象生成不同字符串,所以需要用排序键的序列化逻辑:

    function stableStringify(obj) {
      if (typeof obj !== 'object' || obj === null) return JSON.stringify(obj);
      if (Array.isArray(obj)) return `[${obj.map(stableStringify).join(',')}]`;
      const sortedKeys = Object.keys(obj).sort();
      return `{${sortedKeys.map(k => `"${k}":${stableStringify(obj[k])}`).join(',')}}`;
    }
    

    也可以用更高效的成熟库如fast-json-stable-stringify,减少自己维护代码的成本。

  2. 生成哈希并统计重复项
    用序列化字符串生成哈希,再通过Map快速统计重复:

    // Node.js环境用crypto模块,浏览器可引入如js-sha1等库
    const { createHash } = require('crypto');
    
    function getHash(str) {
      return createHash('sha1').update(str).digest('hex');
    }
    
    function findDuplicates(arr) {
      const hashMap = new Map();
      const duplicates = [];
      for (const obj of arr) {
        const str = stableStringify(obj);
        const hash = getHash(str);
        if (hashMap.has(hash)) {
          // 首次发现重复时加入原对象,后续直接加入当前对象
          if (!hashMap.get(hash).added) {
            duplicates.push(hashMap.get(hash).obj);
            hashMap.get(hash).added = true;
          }
          duplicates.push(obj);
        } else {
          hashMap.set(hash, { obj, added: false });
        }
      }
      return duplicates;
    }
    

优缺点

  • 优势:时间复杂度O(n),数百个对象处理耗时可以忽略;逻辑清晰,扩展性强。
  • 劣势:无法直接处理循环引用的对象,需要额外添加循环引用检测逻辑;依赖序列化的稳定性。

优化版双层循环+深度对比

如果不想用哈希/序列化,针对数百个对象的规模,优化后的双层循环也能满足需求,但性能远不如哈希法:

实现代码

const _ = require('lodash');

function findDuplicates(arr) {
  const duplicates = [];
  const checked = new Array(arr.length).fill(false);
  for (let i = 0; i < arr.length; i++) {
    if (checked[i]) continue;
    let hasDuplicate = false;
    for (let j = i + 1; j < arr.length; j++) {
      if (checked[j]) continue;
      if (_.isEqual(arr[i], arr[j])) {
        if (!hasDuplicate) {
          duplicates.push(arr[i]);
          hasDuplicate = true;
        }
        duplicates.push(arr[j]);
        checked[j] = true;
      }
    }
    if (hasDuplicate) checked[i] = true;
  }
  return duplicates;
}

优缺点

  • 优势:无需处理序列化逻辑,天然支持循环引用的对象;逻辑简单易懂。
  • 劣势:时间复杂度O(n²),当对象数量超过1000时性能会明显下降。

其他方案(不推荐)

原生Set基于浅对比,无法直接用于对象深度去重;若要适配,需重写对象toString或使用第三方库,本质和哈希法类似,没有性能或易用性优势,不建议优先选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:35:42