如何编写TypeScript函数判断两个数组的元素集合是否相等?
解决数组集合相等判断中引用类型元素不匹配的问题
问题描述
使用setEquality函数判断两个包含数组元素的集合是否相等时,出现不符合预期的结果:传入["A", "B", ["C"]]和["A", "B", ["C"]],函数返回false,但预期输出true。
原函数代码:
function setEquality(list1:any[], list2:any[]): boolean { const difference1 = list1.filter(x => !list2.includes(x)); const difference2 = list2.filter(x => !list1.includes(x)); return (difference1.length === 0) && (difference2.length === 0); } console.log(setEquality(["A", "B", ["C"]], ["A", "B", ["C"]])) // 实际输出false
问题原因
Array.includes()使用**严格相等(===)**判断元素是否存在。对于引用类型(比如数组、对象),只有当两个变量指向内存中的同一个对象时,===才会返回true。示例中的两个["C"]是独立创建的数组,引用地址不同,因此list2.includes(["C"])会返回false,导致函数误判。
解决方案
方案1:基于JSON序列化的简洁实现
通过将数组元素序列化为字符串,利用Set的特性比较集合是否相等。这种方式适合处理基本类型和嵌套数组,代码简洁高效:
function setEquality(list1: any[], list2: any[]): boolean { const serialize = (item: any) => JSON.stringify(item); const set1 = new Set(list1.map(serialize)); const set2 = new Set(list2.map(serialize)); if (set1.size !== set2.size) return false; for (const serializedItem of set1) { if (!set2.has(serializedItem)) return false; } return true; } // 测试 console.log(setEquality(["A", "B", ["C"]], ["A", "B", ["C"]])) // true console.log(setEquality(["A", ["C", "D"], "B"], ["A", "B", ["D", "C"]])) // true console.log(setEquality(["A", "B"], ["A", "B", "C"])) // false
注意:该方法依赖JSON.stringify,存在局限性:
- 对象的键顺序不同时,序列化结果会不同(比如
{a:1, b:2}和{b:2, a:1}序列化后字符串不同) - 无法正确处理包含
undefined、函数、Symbol的元素
方案2:深度递归比较实现
通过递归判断元素是否深度相等,支持嵌套数组和对象,适用范围更广:
// 辅助函数:判断两个值是否深度相等 function isDeepEqual(a: any, b: any): boolean { // 基本类型或同一引用直接判断 if (a === b) return true; // 处理数组类型 if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) { if (!isDeepEqual(a[i], b[i])) return false; } return true; } // 处理对象类型(可选扩展) if (typeof a === 'object' && a != null && typeof b === 'object' && b != null) { const keysA = Object.keys(a); const keysB = Object.keys(b); if (keysA.length !== keysB.length) return false; for (const key of keysA) { if (!keysB.includes(key) || !isDeepEqual(a[key], b[key])) return false; } return true; } // 其他不匹配情况 return false; } // 集合相等判断函数 function setEquality(list1: any[], list2: any[]): boolean { // 检查list1的所有元素都在list2中存在(深度相等) for (const item1 of list1) { if (!list2.some(item2 => isDeepEqual(item1, item2))) return false; } // 检查list2的所有元素都在list1中存在(深度相等) for (const item2 of list2) { if (!list1.some(item1 => isDeepEqual(item1, item2))) return false; } return true; } // 测试 console.log(setEquality(["A", "B", ["C"]], ["A", "B", ["C"]])) // true console.log(setEquality(["A", {x:1, y:2}], [{y:2, x:1}, "A"])) // true
优势:能正确处理嵌套数组、对象,不受键顺序影响,支持更多复杂元素类型。
内容的提问来源于stack exchange,提问作者Saqib Ali
相关产品推荐
相关产品推荐

