如何使用Moment.js将含重叠时间范围的数组拆分为非重叠时间组的二维数组
如何用Moment.js拆分重叠时间的日程到无重叠子数组?
嘿,这个问题我之前处理过类似的场景,咱们一步步来搞定它!你说得对,排序是解决这类时间重叠问题的基础,之后的核心是给每个新日程找到一个合适的“无重叠队列”。
首先先提个小细节:你提供的timetable里第二个项的start值多了个0,应该是'2021-11-16T10:00:00',我会在代码里修正这个问题,避免后续时间解析出错。
实现步骤
按开始时间排序
先把所有日程按start字段升序排列,这样我们可以按时间顺序处理每个日程,确保前面的日程都是更早开始的。维护无重叠子数组队列
我们需要一个二维数组来存放各个无重叠的子数组。对于每个排序后的日程,遍历现有的子数组:- 如果某个子数组的最后一个日程的结束时间 不晚于 当前日程的开始时间,说明可以把当前日程加入这个子数组(不会重叠)。
- 如果遍历完所有子数组都找不到合适的,就新建一个子数组来存放当前日程。
完整代码实现
const moment = require('moment'); const timetable = [ { class: 'one', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' }, { class: 'two', start: '2021-11-16T10:00:00', end: '2021-11-16T11:00:00' }, // 修正了start的格式错误 { class: 'three', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' }, ]; // 步骤1:按开始时间升序排序 const sortedTimetable = timetable.sort((a, b) => { const aStart = moment(a.start); const bStart = moment(b.start); return aStart.isBefore(bStart) ? -1 : 1; }); // 步骤2:拆分到无重叠子数组 const result = []; for (const item of sortedTimetable) { let added = false; // 遍历现有子数组,找可以加入的队列 for (const group of result) { const lastItem = group[group.length - 1]; // 检查当前item的开始时间是否晚于等于组内最后一个item的结束时间 if (moment(item.start).isSameOrAfter(lastItem.end)) { group.push(item); added = true; break; } } // 如果没找到合适的队列,新建一个 if (!added) { result.push([item]); } } console.log(result);
代码说明
- 排序逻辑:用
moment(a.start).isBefore(b.start)来比较两个日程的开始时间,确保数组按时间先后排列。 - 重叠判断:
moment(item.start).isSameOrAfter(lastItem.end)是核心判断——如果当前日程的开始时间和上一个日程的结束时间相同或更晚,就说明两个时间不重叠,可以放在同一组。 - 效率:这个方法的时间复杂度是O(n²),对于大多数日常的日程数量来说完全够用;如果是超大量数据,可以考虑用更高效的优先队列(最小堆)来优化找合适子数组的过程,但日常场景下上面的实现已经足够简洁好用。
运行这段代码后,输出结果就和你预期的完全一致啦!
内容的提问来源于stack exchange,提问作者Tosm
相关产品推荐
相关产品推荐

