JavaScript筛选两个对象的公共日期范围并截取对应timeline数据
JavaScript时序对象重叠区间提取方案
核心思路
利用输入数据的固有特性:每个对象的Date数组是连续递增、与timeline数组下标严格一一对应的有序数组,不需要写多层嵌套if判断逐值比对,只需要三步即可完成需求:
- 预处理日期值为时间戳,规避字符串日期比较的隐式转换问题
- 计算两个日期区间的交集边界:交集起点为两个对象日期起点的最大值,交集终点为两个对象日期终点的最小值
- 定位交集边界在两个
Date数组中的对应下标,直接用数组切片方法提取对应位置的timeline值即可
如果计算得到的交集起点大于终点,说明两个对象的日期范围完全无重叠,直接返回空结果即可。
可直接复用的实现代码
/** * 提取两个时序对象的重叠区间timeline数据 * @param {Object} objA 第一个待比对对象,需包含Date、timeline属性 * @param {Object} objB 第二个待比对对象,需包含Date、timeline属性 * @returns {Object} 包含重叠区间的两个timeline数组、对应公共日期数组 */ function getOverlapTimeline(objA, objB) { // 日期转时间戳工具 const parseToTimestamp = (dateStr) => new Date(dateStr).getTime(); const timestampsA = objA.Date.map(parseToTimestamp); const timestampsB = objB.Date.map(parseToTimestamp); // 取两个对象的日期起止边界 const [startA, endA] = [timestampsA[0], timestampsA.at(-1)]; const [startB, endB] = [timestampsB[0], timestampsB.at(-1)]; // 计算重叠区间边界 const overlapStart = Math.max(startA, startB); const overlapEnd = Math.min(endA, endB); // 无重叠直接返回空结构 if (overlapStart > overlapEnd) { return { timelineA: [], timelineB: [], overlapDates: [] }; } // 定位边界在两个数组中的下标 const startIdxA = timestampsA.indexOf(overlapStart); const endIdxA = timestampsA.indexOf(overlapEnd); const startIdxB = timestampsB.indexOf(overlapStart); const endIdxB = timestampsB.indexOf(overlapEnd); // 切片提取目标数据 const timelineA = objA.timeline.slice(startIdxA, endIdxA + 1); const timelineB = objB.timeline.slice(startIdxB, endIdxB + 1); const overlapDates = objA.Date.slice(startIdxA, endIdxA + 1); // 异常兜底校验 if (timelineA.length !== timelineB.length) { console.warn("输入数据的Date数组存在非连续断档,请检查原始数据合法性"); } return { timelineA, timelineB, overlapDates }; }
兼容优化方案
如果你的原始数据可能存在日期缺省、非严格连续的场景,可以把indexOf下标查找替换为有序数组专用的二分查找逻辑,查找效率更高,也能兼容个别日期缺失的异常场景:
// 有序数组二分查找目标值下标,找不到返回-1 function binarySearch(sortedArr, target) { let left = 0; let right = sortedArr.length - 1; while (left <= right) { const mid = Math.floor((left + right) / 2); if (sortedArr[mid] === target) return mid; sortedArr[mid] < target ? (left = mid + 1) : (right = mid - 1); } return -1; } // 替换原代码中indexOf的调用即可 const startIdxA = binarySearch(timestampsA, overlapStart); const endIdxA = binarySearch(timestampsA, overlapEnd); const startIdxB = binarySearch(timestampsB, overlapStart); const endIdxB = binarySearch(timestampsB, overlapEnd);
使用示例
// 比对数组中第1个和第2个对象的重叠区间 const result = getOverlapTimeline(array_of_objects[0], array_of_objects[1]); // 输出的result.timelineA和result.timelineB长度完全一致,下标对应同一个公共日期的数值 console.log(result.timelineA, result.timelineB);
内容的提问来源于stack exchange,提问作者ProperPitch
相关产品推荐
相关产品推荐

