JS对比对象数组多属性值并操作节点 生成带重复标记的新数组
修正后可运行完整代码
const testState = [ { value1: "1", value2: "two", value3: 3, }, { value1: "one", value2: 2, value3: "3", }, { value1: "1", value2: 2, value3: "3", }, ]; const testEquality = (accountArray) => { // 预统计每个key下各值的出现次数,避免重复遍历提升效率 const keyValueCount = {}; // 第一轮遍历做统计 accountArray.forEach(account => { Object.keys(account).forEach(key => { if (typeof account[key] === 'object' && account[key] !== null) return; // 跳过对象类型值 if (!keyValueCount[key]) keyValueCount[key] = {}; const val = account[key]; keyValueCount[key][val] = (keyValueCount[key][val] || 0) + 1; }) }) // 第二轮遍历生成最终结果 return accountArray.map(account => { const processed = {}; Object.keys(account).forEach(key => { const val = account[key]; if (typeof val === 'object' && val !== null) { processed[key] = val; // 第一层以外的值保留原样 return; } processed[key] = { value: val, // 直接查统计结果判断是否有重复,出现次数大于1即存在其他相同值 duplicate: keyValueCount[key][val] > 1 } }) return processed; }) }; // 原testState为const声明不能直接赋值,用新变量接收结果 const processedState = testEquality(testState); console.log(processedState);
运行后输出和你给出的预期完全一致。
核心修正/优化点
- 修复了调用逻辑错误:你原本用
testState.map((obj) => testEquality(obj))是把单个对象传入处理函数,不符合跨对象同key对比的需求,直接传入整个数组即可 - 修复了类型判断错误:你之前判断的是
key的类型,实际应该判断属性值的类型 - 优化了重复判断逻辑:不用每次遍历都生成非当前索引数组再逐一对比,先提前统计每个key下所有值的出现次数,后续判断重复只需查统计结果,数组越大效率优势越明显
- 不需要手动做深拷贝:直接生成新的对象数组,完全不会修改原始输入
贴合你原有思路的非当前索引生成实现
如果你非要按照自己原来的思路生成非当前索引数组,可以用这段逻辑替换处理部分:
accountArray.forEach((account, i) => { // 生成所有非当前索引的数组 const otherIndexes = Array.from({length: accountArray.length}, (_, idx) => idx).filter(idx => idx !== i); for (const key in account) { const val = account[key]; if (typeof val === "object" && val !== null) continue; returnedArray[i][key] = { value: val, // 遍历其他索引对比同key值 duplicate: otherIndexes.some(idx => accountArray[idx][key] === val) }; } });
内容的提问来源于stack exchange,提问作者VolksRat71
相关产品推荐
相关产品推荐

