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

如何编写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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:12:51