TypeScript判断两个数组内容是否相等的实现

作者:木棉

时间:2026-10-31

浏览:658

本文介绍在TypeScript中判断两个数组内容是否相等的多种实现方式,包括直接遍历、利用indexOf与includes的区别处理NaN、给重复元素编号、统计元素次数以及加减抵消法。文章详细分析了各种方法的优缺点及边界情况,如NaN、null、undefined以及类型转换问题,并提供了相应的代码示例。

文章目录

方法一:直接遍历比较

// 1.直接遍历
const arr1: any[] = ["apple", "banana", NaN];
const arr2: any[] = ["apple", NaN, "banana"];

function fn1(arr1: any[], arr2: any[]) {
  // Array.some(): 有一项不满足,返回false
  if (arr1.length !== arr2.length) {
    return false;
  }
  return arr1.some((item: any) => arr2.indexOf(item) === -1) ? false : true;
//   return !arr1.some((item) => !arr2.includes(item));
}
console.log("直接遍历 => ", fn1(arr1, arr2)); // false

NaN值处理存在缺陷

改进方案

// 1.直接遍历
const arr1: any[] = ["apple", "banana", NaN];
const arr2: any[] = ["apple", NaN, "banana"];

function fn1(arr1: any[], arr2: any[]) {
  // Array.some(): 有一项不满足,返回false
  if (arr1.length !== arr2.length) {
    return false;
  }
//   return arr1.some((item: any) => arr2.indexOf(item) === -1) ? false : true;
  return !arr1.some((item) => !arr2.includes(item));
}
console.log("直接遍历 => ", fn1(arr1, arr2)); // true

Array.prototype.indexOf() 采用严格相等算法,导致 NaN 无法匹配;Array.prototype.includes() 采用零值相等算法,将 NaN 视为相等

方法二:对重复元素进行编号标记

// 2.把重复元素标识编号
function fn3(arr1: any[], arr2: any[]) {
  if (arr1.length !== arr2.length) {
    return false;
  }
  // 重复数组元素 加1、2、3
  const countArr1 = updateArray(arr1);
  const countArr2 = updateArray(arr2);

  // arr 数组 元素重复转换成 val1,val2
  function updateArray(arr: any[]) {
    const countMap: Map<any, number> = new Map();
    const updateArr: any[] = [];
    for (const ele of arr) {
      //   const cnt = !countMap.has(ele) ? 1 : countMap.get(ele)! + 1;
      const cnt = (countMap.get(ele) || 0) + 1;
      countMap.set(ele, cnt);
      updateArr.push(`${ele}${cnt}`); // 有问题
      // 等同于
      //   if (!countMap.has(ele)) {
      //     // 如果元素是第一次出现,直接添加到结果数组
      //     countMap.set(ele, 0)
      //     updateArr.push(ele)
      //   } else {
      //     // 如果元素已经出现过,添加带有编号的新元素到结果数组
      //     const count = countMap.get(ele)! + 1
      //     countMap.set(ele, count)
      //     updateArr.push(`${ele}${count}`)
      //   }
    }
    return updateArr;
  }
  // console.log("countArr1 => ", countArr1);
  // console.log("countArr2 => ", countArr2)
  return !countArr1.some((item) => !countArr2.includes(item));
}

const array1 = ["apple", "banana", "cherry", "banana"];
const array2 = ["banana", "apple", "banana", "cherry"];
console.log("把重复元素标识编号 => ", fn3(array1, array2)); // true

// 其实这种存在漏洞的
const array3 = ["apple", "banana", "cherry", "banana", 1, "1", "1"];
const array4 = ["banana", "apple", "banana", "cherry", "1", 1, 1];
// 应该是false
console.log("把重复元素标识编号 存在漏洞 => ", fn3(array3, array4)); // true

方法三:统计各元素出现频次

// 3.统计元素次数
function fn4(arr1: any[], arr2: any[]) {
  if (arr1.length !== arr2.length) {
    return false;
  }
  // 创建计数对象,用于记录每个元素在数组中的出现次数
  const countMap1: Map<any, number> = count(arr1);
  const countMap2: Map<any, number> = count(arr2);

  function count(arr: any[] = []) {
    const map: Map<any, number> = new Map();
    for (const item of arr) {
      map.set(item, (map.get(item) || 0) + 1);
    }
    return map;
  }

  //检查计数对象是否相等

//   console.log("countMap1 => ", countMap1)
//   console.log("countMap2 => ", countMap2)
  for (const [key, count] of countMap1) {
    if (countMap2.get(key) !== count) {
        return false;
    }
  }
  return true;
}

const array5 = ["apple", "banana", "cherry", "banana", 1, "1", "11", 11];
const array6 = ["banana", "apple", "banana", "cherry", "1", 1, "11", 11];

console.log("统计元素次数 => ", fn4(array5, array6)); // true
console.log("统计元素次数 => ", fn4(array3, array4)); // false

方法四:通过+1和-1计数抵消

// 4.+1,-1
function fn5(arr1: any[], arr2: any[]) {
    if (arr1.length !== arr2.length) {
        return false;
    }
    const countMap: Map<any, number> = new Map();

    // 计算第一个数组的元素
    for (const item of arr1) {
        countMap.set(item, (countMap.get(item) || 0) + 1);
    }

    // 比较第二个数组
    for (const item of arr2) {
        const val = countMap.get(item)
        if (val === undefined || val <= 0) {
            return false;
        }
        countMap.set(item, val - 1)
    }
    return true;
}
console.log("+1, -1 => ", fn5(array3, array4)) // false
console.log("+1, -1 => ", fn5(array5, array6))  // true

总结

  • 首先检查数组长度,若长度不一致则直接判定为不相等
  • 允许数组元素重复存在
  • 需考虑边界情况
    • 字符串 '1' 与数字 1 的区别(Object键值强制为字符串,Map键值无此限制)
    • NaN值的特殊处理
    • null与undefined值的处理

相关技术知识

JavaScript规范中定义的相等、严格相等、零值相等及同值相等概念

  • 非严格相等运算符:==
  • 严格相等运算符:===(应用于Array.prototype.indexOf()、Array.prototype.lastIndexOf()及case语句匹配)
  • 零值相等:应用于%TypeArray%和ArrayBuffer构造函数、Map和Set操作、String.prototype.includes()
  • 同值相等:应用于其余所有比较场景

零值相等:机制同于同值相等,但规定 +0 与 -0 相等

同值相等:用于判定两个值在功能上是否在任何情况下完全相同

至此,关于TypeScript判断两个数组内容是否相等的实现介绍完毕,更多相关TypeScript判断数组内容相等内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章