如何用JavaScript合并重叠起止时间生成无重叠营业时间列表
如何合并JavaScript中的重叠营业时间区间
要解决合并重叠/重复营业时间的问题,核心思路是先排序再遍历合并,这是处理区间合并问题的标准高效方案(时间复杂度O(n log n),主要来自排序步骤)。
正确实现代码
const mergeHours = (hours) => { // 空数组直接返回 if (hours.length === 0) return []; // 1. 按开始时间排序,确保按时间顺序处理 const sortedHours = [...hours].sort((a, b) => { // "HH:MM"格式的时间字符串可直接按字典序比较 return a.start.localeCompare(b.start); }); // 2. 初始化结果数组,放入第一个区间 const merged = [sortedHours[0]]; // 3. 遍历剩余区间,逐个合并 for (let i = 1; i < sortedHours.length; i++) { const current = sortedHours[i]; const lastMerged = merged[merged.length - 1]; // 如果当前区间的开始时间 <= 最后一个合并区间的结束时间,说明有重叠/相邻,合并 if (current.start <= lastMerged.end) { lastMerged.end = Math.max(lastMerged.end, current.end); } else { // 无重叠,直接加入结果数组 merged.push(current); } } return merged; }; // 测试示例 const mondayHours = [ { start: "09:00", end: "14:00" }, { start: "10:00", end: "15:00" }, { start: "17:00", end: "23:00" }, ]; console.log(mergeHours(mondayHours)); // 输出:[{ start: "09:00", end: "15:00" }, { start: "17:00", end: "23:00" }]
为什么你找到的在线方案不生效?
你提供的代码逻辑存在根本性错误:
- 嵌套循环的处理方向完全搞反了:它试图在两两比较时,把
aStart更新为更大的bStart,aEnd更新为更小的bEnd,这是在缩小区间,而非合并重叠区间。 - 这种实现不仅无法合并重叠区间,甚至可能生成错误的时间范围,完全不符合需求。
额外优化:时间格式转换(可选)
如果需要把合并后的HH:MM格式转换为12小时制(比如9am-3pm),可以添加一个辅助函数:
const formatTime = (timeStr) => { const [hours, minutes] = timeStr.split(":").map(Number); const period = hours >= 12 ? "pm" : "am"; const formattedHours = hours % 12 || 12; // 分钟为0时省略,否则补零保留 return minutes === 0 ? `${formattedHours}${period}` : `${formattedHours}:${minutes.toString().padStart(2, '0')}${period}`; }; // 生成最终显示文本 const getDisplayText = (mergedHours) => { const formatted = mergedHours.map(h => `${formatTime(h.start)}-${formatTime(h.end)}`); return `Open: ${formatted.join(', ')}`; }; console.log(getDisplayText(mergeHours(mondayHours))); // 输出:Open: 9am-3pm, 5pm-11pm
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

