我正在工作的班次调度系统,需要协助合并两个数组的班次对象.每个移位对象定义如下:

type Shift = { start: Date, end: Date, users: string[] }

第一个数组表示即将到来的移位,其中连续元素的结束时间和开始时间之间没有间隔.第二个数组包含"覆盖",这是分散的移位,可以设置为任何时间而不重叠.

我的目标是将这两个数组合并到一个表示最终排班表的数组中.然而,我正在努力处理所有的变化,例如覆盖整个班次或发生在班次中间的覆盖.

有没有适用于这种情况的数据 struct ,以及可以帮助我高效实现此计算的任何算法方法?

--编辑--

移位数组-

[
{start: "01-07-2023 00:00", end: "02-07-2023 00:00", users: ['a']},
{start: "02-07-2023 00:00", end: "03-07-2023 00:00", users: ['b']},
{start: "03-07-2023 00:00", end: "04-07-2023 00:00", users: ['c']},
{start: "04-07-2023 00:00", end: "05-07-2023 00:00", users: ['a']},
{start: "05-07-2023 00:00", end: "06-07-2023 00:00", users: ['b']}
]

覆盖:

[
{start: "01-07-2023 10:00", end: "01-07-2023 15:00", users: ['d']},
{start: "04-07-2023 01:00", end: "05-07-2023 12:00", users: ['e']},
{start: "02-07-2023 00:00", end: "03-07-2023 00:00", users: ['f']}
]

最终结果-

[
{start: "01-07-2023 00:00", end: "01-07-2023 10:00", users: ['a']},
{start: "01-07-2023 10:00", end: "01-07-2023 15:00", users: ['d']},
{start: "01-07-2023 15:00", end: "02-07-2023 00:00", users: ['a']},
{start: "02-07-2023 00:00", end: "03-07-2023 00:00", users: ['f']},
{start: "03-07-2023 00:00", end: "04-07-2023 00:00", users: ['c']},
{start: "04-07-2023 00:00", end: "04-07-2023 01:00", users: ['a']},
{start: "04-07-2023 01:00", end: "05-07-2023 12:00", users: ['e']},
{start: "05-07-2023 12:00", end: "06-07-2023 00:00", users: ['b']}
]

推荐答案

您可以按开始日期对两个数组进行排序(转换为ISO格式以进行词法排序),然后通过剪裁覆盖两侧的移位并跳过完全重叠的移位来执行合并.

// Helper functions to toggle between DMY and YMD formats, to make dates lexically ordered:
const toggleIso = (s) => s?.replace(/^(\d+)-(\d+)-(\d+) (.*)$/, "$3-$2-$1 $4");
const toggleIsoMap = arr =>
    arr.map(o => ({ ...o, start: toggleIso(o.start), end: toggleIso(o.end) }))
       .sort((a, b) => a.start.localeCompare(b.start));

function mergeShifts(shifts, overrides) {
    overrides = toggleIsoMap(overrides);
    const shiftIter = toggleIsoMap(shifts).values();
    const nextShift = () => shiftIter.next().value;

    const result = [];

    let shift = nextShift();    
    for (const override of overrides) {
        // Flush all shifts that come before this override
        while (shift?.end < override.start) { 
            result.push(shift);
            shift = nextShift();
        }
        // The override may make a shift end sooner
        if (shift?.start < override.start) result.push({...shift, end: override.start });
        result.push(override);
        // Skip shifts that are entirely within the override
        while (shift?.end <= override.end) shift = nextShift();
        // The override may make a shift start later
        if (shift?.start < override.end) shift = {...shift, start: override.end };
    }
    if (shift) result.push(shift);
    return toggleIsoMap(result.concat(...shiftIter));
}

// Run with your example input 
const shifts = [
    {start: "01-07-2023 00:00", end: "02-07-2023 00:00", users: ['a']},
    {start: "02-07-2023 00:00", end: "03-07-2023 00:00", users: ['b']},
    {start: "03-07-2023 00:00", end: "04-07-2023 00:00", users: ['c']},
    {start: "04-07-2023 00:00", end: "05-07-2023 00:00", users: ['a']},
    {start: "05-07-2023 00:00", end: "06-07-2023 00:00", users: ['b']}
];
const overrides = [
    {start: "01-07-2023 10:00", end: "01-07-2023 15:00", users: ['d']},
    {start: "04-07-2023 01:00", end: "05-07-2023 12:00", users: ['e']},
    {start: "02-07-2023 00:00", end: "03-07-2023 00:00", users: ['f']}
];

const result = mergeShifts(shifts, overrides);
for (const entry of result) console.log(JSON.stringify(entry));

Node.js相关问答推荐

无法从ejs Web应用程序中的正文中提取数据

CloudTasksClient在Firebase Function % s onDocumentCreated中实例化时导致错误

使用NodeJS输出检索Base64图像的网络报废

关于Node.js中的AES加密库的问题

如何修复PostgreSQL和NodeJS/NestJS应用程序之间的日期时间和时区问题?

车把模板引擎循环问题

使用 playwright 获取页面中同一 url 的所有响应

我需要聚合两个 MongoDB 集合

mongoose findOneAndUpdate 不更新数据库

我如何在 Raku 的供应中注册不同的事件?

为什么要加密 CSRF 令牌?

为什么 FastAPI 需要 Web 服务器(即 Nginx)而不是 Express API?

当其中一个端点不工作时,如何使用 axios.all() 调用多个 API?

使用 Forms API 进行批量更新时生成 itemId

从数据库读取数据并将其作为可下载的 zip 文件发送

获取数组的至少一个元素包含子字符串的文档

NestJS 共享模块的问题

Node.js、Cygwin 和 Socket.io 走进一家wine 吧……Node.js 抛出 ENOBUFS,所有人都死了

容器之间的 Docker HTTP 请求

npm install packagename --save-dev 不更新 package.json