首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何重组连续的免费时隙

如何重组连续的免费时隙
EN

Stack Overflow用户
提问于 2021-04-05 15:10:55
回答 1查看 50关注 0票数 0

我正在制作MERN堆栈的API,并且在一条重要的路线上挣扎。

这里是我返回的自由插槽的一个例子。

代码语言:javascript
复制
[
  {
    booked: false,
    startAt: 2025-03-03T07:00:00.000Z,
    endAt: 2025-03-03T07:15:00.000Z,
  },
  {
    booked: false,
    startAt: 2025-03-03T07:15:00.000Z,
    endAt: 2025-03-03T07:30:00.000Z,

  },
  {
    booked: false,
    startAt: 2025-03-03T07:45:00.000Z,
    endAt: 2025-03-03T08:00:00.000Z,
  },
  {
    booked: false,
    startAt: 2025-03-03T08:00:00.000Z,
    endAt: 2025-03-03T08:15:00.000Z,
  },
  {
    booked: false,
    startAt: 2025-03-03T08:15:00.000Z,
    endAt: 2025-03-03T08:30:00.000Z,
  
  },
  {
    booked: false,
    startAt: 2025-03-03T10:15:00.000Z,
    endAt: 2025-03-03T10:30:00.000Z,
  
  },
  {
    booked: false,
    startAt: 2025-03-03T10:30:00.000Z,
    endAt: 2025-03-03T10:45:00.000Z,
  
  }
]

并希望将它们重新组合为2或3个连续时隙,如:

代码语言:javascript
复制
//Grouped by 2 with slot3 booked
[[slot1, slot2],[slot4,slot5],[slot5,slot6]]

//Grouped by 3 with all slots free
[[slot1, slot2,slot3],[slot2, slot3,slot4],[slot3, slot4,slot5],[slot4,slot5,slot6]]

有人有主意吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-05 16:14:57

几乎可以肯定,在reduce中有一种稍微更有效的方法,但是这个版本非常简单,对于大多数合理的情况来说,它的性能都足够高:

代码语言:javascript
复制
// utility function
const aperture = (n) => (xs) =>
  [...xs .keys ()] .slice (0, 1 - n) .map (i => xs .slice (i, i + n))


// main function
const groupSlots = (n, slots) => 
  aperture (n) (slots) .filter (group => group .every (({booked}) => ! booked))


// just to format output
const display = (o) => console .log (JSON.stringify (o, null, 4))

// sample data
const sixSlotsThirdBooked = [{booked: false, startAt: '2025-03-03T07:00:00.000Z', endAt: '2025-03-03T07:15:00.000Z'}, {booked: false, startAt: '2025-03-03T07:15:00.000Z', endAt: '2025-03-03T07:30:00.000Z'}, {booked: true, startAt: '2025-03-03T07:45:00.000Z', endAt: '2025-03-03T08:00:00.000Z'}, {booked: false, startAt: '2025-03-03T08:00:00.000Z', endAt: '2025-03-03T08:15:00.000Z'}, {booked: false, startAt: '2025-03-03T08:15:00.000Z', endAt: '2025-03-03T08:30:00.000Z'}, {booked: false, startAt: '2025-03-03T08:30:00.000Z', endAt: '2025-03-03T08:45:00.000Z'}]
// demo
display (groupSlots (2, sixSlotsThirdBooked))

// sample data
const sixFreeSlots = [{booked: false, startAt: '2025-03-03T07:00:00.000Z', endAt: '2025-03-03T07:15:00.000Z'}, {booked: false, startAt: '2025-03-03T07:15:00.000Z', endAt: '2025-03-03T07:30:00.000Z'}, {booked: false, startAt: '2025-03-03T07:45:00.000Z', endAt: '2025-03-03T08:00:00.000Z'}, {booked: false, startAt: '2025-03-03T08:00:00.000Z', endAt: '2025-03-03T08:15:00.000Z'}, {booked: false, startAt: '2025-03-03T08:15:00.000Z', endAt: '2025-03-03T08:30:00.000Z'}, {booked: false, startAt: '2025-03-03T08:30:00.000Z', endAt: '2025-03-03T08:45:00.000Z'}]
// demo
display (groupSlots (3, sixFreeSlots))
代码语言:javascript
复制
.as-console-wrapper {max-height: 100% !important; top: 0}

助手函数aperture (n)沿着数据移动一个长度为n的滑动窗口,例如,aperture (2) (['a', 'b', 'c', 'd'])将产生[['a', 'b'], ['b', 'c'], ['c', 'd']]

主函数groupSlots,在输入插槽数组上调用aperture,然后过滤掉那些有预定插槽的组。

(我们还包括一个简单的display函数,以避开StackOverflow引入的用于描述包含对某些值的多个引用的对象的稍微奇怪的格式。但这只是一个小的格式化部分。)

更新

在另一项要求之后(请注意,我在对帖子的最初评论中确实提出了这个问题!),我们也可以这样做,但我们需要额外的助手功能来将我们的工作限制在相邻的块上:

代码语言:javascript
复制
// utility functions
const aperture = (n) => (xs) =>
  [...xs .keys ()] .slice (0, 1 - n) .map (i => xs.slice(i, i + n))

const last = (xs) =>
  xs [xs .length - 1]

const groupWith = (fn) => (xs) =>
  xs .reduce (
    (r, x, i, a) => i == 0 
      ? [[x]]
    : fn (last (last (r)), x)
      ? [... r .slice (0, -1), [... last (r), x]]
    : [...r, [x]],
    []
  )


// main function
const groupSlots = (n, slots) => 
  groupWith (({endAt}, {startAt}) => endAt == startAt) (slots .filter (({booked}) => ! booked)) 
    .flatMap (
      group => aperture (n) (group) 
    )
    
    
// just to format output
const display = (o) => console .log (JSON.stringify (o, null, 4))
    

// sample data
const slotsWithBreaks = [
  {booked: false, startAt: '2025-03-03T07:00:00.000Z', endAt: '2025-03-03T07:15:00.000Z'}, 
  {booked: false, startAt: '2025-03-03T07:15:00.000Z', endAt: '2025-03-03T07:30:00.000Z'}, 
  {booked: false, startAt: '2025-03-03T07:30:00.000Z', endAt: '2025-03-03T07:45:00.000Z'}, 
  {booked: false, startAt: '2025-03-03T07:45:00.000Z', endAt: '2025-03-03T08:00:00.000Z'}, 
  {booked: false, startAt: '2025-03-03T08:00:00.000Z', endAt: '2025-03-03T08:15:00.000Z'}, 
  {booked: false, startAt: '2025-03-03T08:15:00.000Z', endAt: '2025-03-03T08:30:00.000Z'}, 
  {booked: false, startAt: '2025-03-03T08:30:00.000Z', endAt: '2025-03-03T08:45:00.000Z'},
  /* ... coffee break ...*/
  {booked: false, startAt: '2025-03-03T09:00:00.000Z', endAt: '2025-03-03T09:15:00.000Z'},
  {booked: false, startAt: '2025-03-03T09:15:00.000Z', endAt: '2025-03-03T09:30:00.000Z'},
  {booked: false, startAt: '2025-03-03T09:30:00.000Z', endAt: '2025-03-03T09:45:00.000Z'},
  {booked: true,  startAt: '2025-03-03T09:45:00.000Z', endAt: '2025-03-03T10:00:00.000Z'},
  /* ... weekly meeting ... */
  {booked: true,  startAt: '2025-03-03T11:00:00.000Z', endAt: '2025-03-03T11:15:00.000Z'},
  {booked: false, startAt: '2025-03-03T11:15:00.000Z', endAt: '2025-03-03T11:30:00.000Z'},
  {booked: false, startAt: '2025-03-03T11:30:00.000Z', endAt: '2025-03-03T11:45:00.000Z'},
  {booked: false, startAt: '2025-03-03T11:45:00.000Z', endAt: '2025-03-03T12:00:00.000Z'},  
  /* ... lunch ... */
  // ...
]

// demo
display (groupSlots (3, slotsWithBreaks))
代码语言:javascript
复制
.as-console-wrapper {max-height: 100% !important; top: 0}

我们添加了一个简单的实用函数last,,它返回数组中的最后一个元素。我们在groupWith,中使用last,它接受一个谓词,并返回一个函数,该函数根据谓词在提供两个连续数组元素时是否返回true,将数组的元素组合在一起。

然后更新我们的主要函数,将时隙分解为(未预订的)时隙的连续数组,并对这些时隙调用aperture,将结果平面映射到一个数组中。请注意,由于我们已经必须根据不可预订的插槽将输出数组分开,所以最简单的方法是先删除预定的插槽,而不是在早期版本中使用检查,即组中的所有插槽实际上都没有预订。

我对groupWith的这种实现并不感兴趣,我认为可能还有更优雅的东西。但我认为它能胜任这项工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66955208

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档