TypeScript中如何正确拆分两个重叠的数值范围?
两个重叠数值范围拆分的实现方案
原实现的核心缺陷
- 存在语法错误:拆分A范围的分支里出现
Math.min(a),未传入必要的比较参数,直接运行会报错 - 逻辑错位:没有按照分割点切分原始范围,最终返回的B段是两个完全相同的原始Range,完全没有实现拆分效果
- 边界判断混乱:硬编码的交集拆分逻辑重复赋值,没有覆盖包含、部分重叠等所有场景,容易生成
start > end的无效范围 - 结果结构不符合预期:没有区分A、B的拆分结果列表,逻辑冗余度高
通用实现思路
拆分两个重叠范围不需要单独计算交集,核心逻辑可以拆解为3步:
- 提取两个原始Range的所有边界坐标,排序后去重,得到所有关键分割节点
- 用相邻的两个分割节点生成候选子范围,过滤掉零长度的无效段
- 按照候选段和原始Range的包含关系,分别筛选出属于A的拆分段、属于B的拆分段
这个思路可以覆盖所有边界场景:部分重叠、一方完全包含另一方、完全不重叠、仅端点接触,输出完全匹配你给出的示例结构。
可直接运行的TypeScript实现
type Range = { start: number; end: number; }; function splitOverlap(a: Range, b: Range): Range[][] { // 提取、排序、去重所有边界点 const rawPoints = [a.start, a.end, b.start, b.end]; const sortedPoints = [...new Set(rawPoints.sort((x, y) => x - y))]; // 生成所有相邻点构成的有效子段 const validSegments: Range[] = []; for (let i = 0; i < sortedPoints.length - 1; i++) { const segStart = sortedPoints[i]; const segEnd = sortedPoints[i + 1]; // 跳过无效的零长度段 if (segStart >= segEnd) continue; validSegments.push({ start: segStart, end: segEnd }); } // 分别筛选属于原始A、B的拆分段 const aSplitSegments = validSegments.filter( seg => seg.start >= a.start && seg.end <= a.end ); const bSplitSegments = validSegments.filter( seg => seg.start >= b.start && seg.end <= b.end ); return [aSplitSegments, bSplitSegments]; }
效果匹配验证
对照你给出的两个测试场景:
- 部分重叠场景(A:15,B:37)
- 边界点序列:1、3、5、7
- A的拆分结果:
[1~3, 3~5] - B的拆分结果:
[3~5, 5~7]
完全匹配示例输出结构
- 包含关系场景(A:17,B:35)
- 边界点序列:1、3、5、7
- A的拆分结果:
[1~3, 3~5, 5~7] - B的拆分结果:
[3~5]
完全匹配示例输出结构
边界场景兼容特性
- 两个范围完全不重叠时,直接返回原始范围本身,无多余拆分
- 仅端点接触的范围,不会生成无效零长度段
- 拆分后的所有段无重叠、无空隙,完全覆盖原始范围的全部数值区间
内容的提问来源于stack exchange,提问作者SMH
相关产品推荐
相关产品推荐

