预订系统资源可用性检查逻辑的优化方案咨询
预订系统资源可用性检查逻辑的优化方案咨询
嘿,我仔细看了你的资源预订系统代码和问题,确实随着资源和预订量增长,当前的写法会出现性能瓶颈,咱们一步步来优化它:
现有代码的核心问题
- 重复过滤预订列表:每次遍历资源时都用
filter去bookingList里找对应资源的预订,这会导致时间复杂度达到O(R*B)(R是资源数,B是总预订数),数据量一大就会变慢。 - 重复日期转换:每次检查预订时都把字符串日期转成
Date对象,做了很多没必要的重复工作。 - 静态
status字段误导:你现在只检查status为"Booked"的资源,但其实"Available"状态的资源可能也需要确认(比如会不会有未更新status的情况?),而且静态状态不如实际预订日期准确。
优化方案
1. 重构预订数据结构,提前分组
先把bookingList转换成按resourceId为键的对象,这样不用每次都过滤,直接通过资源ID就能拿到对应的所有预订,时间复杂度降到O(R + B)(预处理一次,后续直接查询)。
2. 提前转换日期为时间戳
把所有预订的日期和请求日期都提前转成时间戳(毫秒数),这样比较日期的时候不用重复创建Date对象,更快更高效。
3. 优化循环终止条件
一旦找到足够数量的可用资源(比如你例子里的requiredResources = 1),就立刻终止循环,不用再检查剩下的资源。
4. 去掉冗余的静态status检查
直接通过预订日期判断可用性,不管资源的静态status,避免状态不一致导致的错误。
优化后的代码示例
// 预处理:把预订列表按resourceId分组,同时转换日期为时间戳 const bookingsByResource = bookingList.reduce((acc, booking) => { const resourceId = booking.resourceId; if (!acc[resourceId]) { acc[resourceId] = []; } acc[resourceId].push({ start: new Date(booking.startDate).getTime(), end: new Date(booking.endDate).getTime() }); return acc; }, {}); // 请求日期转时间戳 const requestStart = new Date("2025-01-15").getTime(); const requestEnd = new Date("2025-01-19").getTime(); let availableResources = []; let newBookings = []; const requiredResources = 1; // 遍历资源列表,找到足够的可用资源就停止 for (const resource of resourceList) { if (availableResources.length >= requiredResources) break; const resourceBookings = bookingsByResource[resource.resourceId] || []; // 检查是否与任何预订重叠 const isAvailable = resourceBookings.every(booking => { // 不重叠的条件:请求结束时间 <= 现有预订开始, 或者 请求开始时间 >= 现有预订结束 return requestEnd <= booking.start || requestStart >= booking.end; }); if (isAvailable) { availableResources.push(resource.resourceId); newBookings.push({ resourceId: resource.resourceId, startDate: new Date(requestStart).toISOString().split("T")[0], endDate: new Date(requestEnd).toISOString().split("T")[0] }); } } console.log("可用资源:", availableResources); console.log("新增预订:", newBookings);
进一步的进阶优化
如果你的系统预订量非常大(比如上万条),可以给每个资源的预订列表按开始日期排序,然后用二分查找来快速判断是否有重叠,这样单资源的检查时间会从O(B)降到O(logB),性能提升更明显:
// 预处理时给每个资源的预订按开始时间排序 const bookingsByResource = bookingList.reduce((acc, booking) => { const resourceId = booking.resourceId; const start = new Date(booking.startDate).getTime(); const end = new Date(booking.endDate).getTime(); if (!acc[resourceId]) { acc[resourceId] = []; } acc[resourceId].push({ start, end }); return acc; }, {}); // 给每个资源的预订排序 Object.values(bookingsByResource).forEach(bookings => { bookings.sort((a, b) => a.start - b.start); }); // 用二分查找检查重叠 function isResourceAvailable(bookings, reqStart, reqEnd) { let left = 0; let right = bookings.length - 1; while (left <= right) { const mid = Math.floor((left + right) / 2); const booking = bookings[mid]; // 如果请求时间段与当前预订重叠,直接返回不可用 if (!(reqEnd <= booking.start || reqStart >= booking.end)) { return false; } // 如果请求结束时间 <= 当前预订开始,去左边找更早的预订 if (reqEnd <= booking.start) { right = mid - 1; } else { // 否则去右边找更晚的预订 left = mid + 1; } } return true; } // 后续遍历资源时调用这个函数 // const isAvailable = isResourceAvailable(resourceBookings, requestStart, requestEnd);
这样处理后,即使数据量很大,系统也能保持高效运行~
备注:内容来源于stack exchange,提问作者sara ameen
相关产品推荐
相关产品推荐

