Angular开发中JavaScript多数值范围重叠检测的简化实现问询
检测数值范围重叠的简洁实现
先说说你现有代码的问题:
- 循环里错用了
arr[index],应该是arr[i],不然一直在和当前元素自己比较 - 循环条件
i < arr.length-1会漏掉最后一个元素的检查 - 内层循环里的
return false会导致只要第一个不重叠就直接返回,没检查完所有其他元素
下面给你几种更简洁可靠的实现方式:
方法一:排序后检查相邻范围(高效)
如果不需要保留原数组顺序,先按起始值排序,之后只需要检查相邻范围是否重叠就行,时间复杂度O(n log n),大数据量下更高效:
const hasOverlap = (ranges: [number, number][]): boolean => { if (ranges.length <= 1) return false; // 按起始值升序排序,避免修改原数组 const sorted = [...ranges].sort((a, b) => a[0] - b[0]); // 遍历检查相邻范围 return sorted.some((range, idx) => { if (idx === 0) return false; const prevRange = sorted[idx - 1]; // 当前范围的起始值 <= 前一个范围的结束值,说明重叠 return range[0] <= prevRange[1]; }); }; // 测试示例 const rangeArr = [[5,10], [15,20], [9,14]]; console.log(hasOverlap(rangeArr)); // 输出 true
方法二:双重循环简化判断(直观)
如果要保留原数组顺序,用some方法配合双重循环,把重叠判断逻辑简化:
const hasOverlap = (ranges: [number, number][]): boolean => { return ranges.some((rangeA, i) => { return ranges.some((rangeB, j) => { if (i === j) return false; // 跳过自己和自己比较 // 两个范围重叠的核心条件:A的起始 <= B的结束 且 A的结束 >= B的起始 return rangeA[0] <= rangeB[1] && rangeA[1] >= rangeB[0]; }); }); }; // 测试示例 const rangeArr = [[5,10], [15,20], [9,14]]; console.log(hasOverlap(rangeArr)); // 输出 true
方法三:单循环结合slice(更紧凑)
用slice跳过已检查过的元素,避免重复比较,代码更简洁:
const hasOverlap = (ranges: [number, number][]): boolean => { return ranges.some((range, idx) => { // 只和当前元素之后的元素比较,避免重复检查 return ranges.slice(idx + 1).some(other => range[0] <= other[1] && range[1] >= other[0] ); }); };
核心逻辑说明
不管哪种方法,判断两个范围[a1,a2]和[b1,b2](假设起始值<=结束值)重叠的核心条件都是:a1 <= b2 && a2 >= b1,这个条件能覆盖所有重叠场景,包括包含、部分重叠、完全重合的情况。
内容的提问来源于stack exchange,提问作者Tomas Katz
相关产品推荐
相关产品推荐

