【问题标题】:Sort array(gantt schedule) based on date + duration(min) - with static breaks(date+duration)根据日期+持续时间(分钟)对数组(甘特计划)进行排序 - 带有静态中断(日期+持续时间)
【发布时间】:2020-03-20 11:06:04
【问题描述】:

我有一个基于甘特图的数组。该数组包含具有以下属性的对象

{
    id: string;
    startTime: Date;
    durationEstimated: number;
    isBreak: boolean;
}

和一些通用值。基于这些值,我需要遍历数组并根据以前的值对 startTime 进行排序/更新。在这样做的同时,我还需要考虑“isBreak”(静态值 - startTime/durationEstimated 永远不会改变)

例如,假设我有这个数组:

[ 
    {id: '1', startTime: "2020-04-01T08:30:00", durationEstimated: 60, isBreak: false},
    {id: '2', startTime: "2020-04-01T09:00:00", durationEstimated: 15, isBreak: true},
    {id: '3', startTime: "2020-04-01T09:45:00", durationEstimated: 60, isBreak: false},
    {id: '4', startTime: "2020-04-01T10:45:00", durationEstimated: 60, isBreak: false},
    {id: '5', startTime: "2020-04-01T11:45:00", durationEstimated: 60, isBreak: false},
    {id: '6', startTime: "2020-04-01T12:00:00", durationEstimated: 60, isBreak: true},
    {id: '7', startTime: "2020-04-01T13:45:00", durationEstimated: 60, isBreak: false}
] 

第一个 item(id='1'),将运行 30 分钟。然后 break(id='2') 15 分钟,然后在开始下一个 item(id='3') 之前完成最后 30 分钟。 (新项目永远不会添加到 pos 0 )

假设我需要在其中添加另一个对象(开始时间无关)

{id: '8', startTime: "2022-05-01T14:30:00", durationEstimated: 60, isBreak: false} 

我将它推入 pos 1 的数组中,然后数组将如下所示:

[ 
    {id: '1', startTime: "2020-04-01T09:30:00", durationEstimated: 60, isBreak: false}, 
    {id: '8', startTime: "2022-05-01T14:30:00", durationEstimated: 60, isBreak: false} 
    {id: '2', startTime: "2020-04-01T09:00:00", durationEstimated: 15, isBreak: true}, 
    {id: '3', startTime: "2020-04-01T09:45:00", durationEstimated: 60, isBreak: false}, 
    {id: '4', startTime: "2020-04-01T10:45:00", durationEstimated: 60, isBreak: false},
    {id: '5', startTime: "2020-04-01T11:45:00", durationEstimated: 60, isBreak: false},
    {id: '6', startTime: "2020-04-01T12:00:00", durationEstimated: 60, isBreak: true},
    {id: '7', startTime: "2020-04-01T13:45:00", durationEstimated: 60, isBreak: false}
] 

这是我想在第一个元素之后开始排序和更新所有元素的 startTime 的地方。所以它应该将物品移动到适合的休息时间。

预期结果:

[ 
    {id: '1', startTime: "2020-04-01T08:30:00", durationEstimated: 60, isBreak: false}, 
    {id: '2', startTime: "2020-04-01T09:00:00", durationEstimated: 15, isBreak: true}, 
    {id: '8', startTime: "2020-04-01T09:45:00", durationEstimated: 60, isBreak: false},
    {id: '3', startTime: "2020-04-01T10:45:00", durationEstimated: 60, isBreak: false}, 
    {id: '4', startTime: "2020-04-01T11:45:00", durationEstimated: 60, isBreak: false},
    {id: '6', startTime: "2020-04-01T12:00:00", durationEstimated: 60, isBreak: true},
    {id: '5', startTime: "2020-04-01T13:45:00", durationEstimated: 60, isBreak: false},
    {id: '7', startTime: "2020-04-01T14:45:00", durationEstimated: 60, isBreak: false}
] 

真正的数组大约有 60-80 行长,并且包含多个中断 + 不同的 durationEstimated 值。

试过

当我必须在数组中移动项目以考虑休息时间时,我总是会遇到问题。

我的想法是遍历数组检查每个项目,将其与前一个项目进行比较(startTime+duration)并将新日期添加到当前迭代项目startTime。然后通过每个项目执行此操作。问题是何时发生中断,因为它们是静态的并且永远不会更新。

如果你只将新项目添加到数组的最后一个位置,我就可以工作了(因为我不需要排序,只能检查以前的值)。但在实际应用中,任何位置都会添加新项目。

【问题讨论】:

  • 我认为 id=8 上的 2022 有时是拼写错误?
  • 所以基本上,休息的时间应该不用管,但是其他项目的时间可以改变吗?是只有在条目已经插入位置1之后才需要这样做,还是在插入时可以这样做?
  • 正如我在问题中所说,插入对象中的日期无关紧要。排序时会更新。插入后需要进行排序。

标签: javascript arrays sorting duration


【解决方案1】:

不知道如何将其转换为 JavaScript,但我认为我有一个用 Python 编写的解决方案似乎可以正常工作。

import datetime, json

data = [ 
    {'id': '1', 'startTime': "2020-04-01T08:30:00", 'durationEstimated': 60, 'isBreak': False},
    {'id': '2', 'startTime': "2020-04-01T09:00:00", 'durationEstimated': 15, 'isBreak': True},
    {'id': '3', 'startTime': "2020-04-01T09:45:00", 'durationEstimated': 60, 'isBreak': False},
    {'id': '4', 'startTime': "2020-04-01T10:45:00", 'durationEstimated': 60, 'isBreak': False},
    {'id': '5', 'startTime': "2020-04-01T11:45:00", 'durationEstimated': 60, 'isBreak': False},
    {'id': '6', 'startTime': "2020-04-01T12:00:00", 'durationEstimated': 60, 'isBreak': True},
    {'id': '7', 'startTime': "2020-04-01T13:45:00", 'durationEstimated': 60, 'isBreak': False}
]

new_data = []

original_data_in_dict_form = {}
breaks = {}
sort_dict = {}
for item in data:
    start_date_obj = datetime.datetime.strptime(item['startTime'], "%Y-%m-%dT%H:%M:%S")

    if item['isBreak']:
        breaks[item['id']] = item
        breaks[item['id']]['endTime'] = start_date_obj + datetime.timedelta(minutes=item['durationEstimated'])
    else:
        original_data_in_dict_form[item['id']] = item
        original_data_in_dict_form[item['id']]['endTime'] = start_date_obj + datetime.timedelta(minutes=item['durationEstimated'])

for break_id in breaks:
    for original_id in original_data_in_dict_form:
        if breaks[break_id]['startTime'] > original_data_in_dict_form[original_id]['startTime'] and breaks[break_id]['endTime'] < original_data_in_dict_form[original_id]['endTime']:
            original_data_in_dict_form[original_id]['endTime'] += datetime.timedelta(minutes=breaks[break_id]['durationEstimated'])
        if original_id not in sort_dict:
            sort_dict[original_id] = original_data_in_dict_form[original_id]['endTime']

for original_id, end_time in sorted(sort_dict.items(), key=lambda p: p[1], reverse=False):
    new_data.append(original_data_in_dict_form[original_id])

print(new_data)

endTime 上排序,显然可以转换为其他内容。这很可能是非常低效的,但应该能让你继续前进。

【讨论】:

    【解决方案2】:

    在 Torxed 答案的帮助下,我设法让它工作。

    首先我遍历每个项目并设置一个结束时间

    items = items.map(item => {
        item.startTime = new Date(item.startTime);
        const endTime = new Date(item.startTime);
        endTime.setMinutes(endTime.getMinutes() + item.durationEstimated);
        item.endTime = endTime;
        return item;
    });
    

    接下来我过滤出 real*" 和 **break 项到数组中

    const realItems = items.filter(x => !x.break);
    const breakItems = items.filter(x => x.break);
    

    遍历所有 realItems

    从以前的值endTime

    设置startTime

    获取项目startTime + duration = endTime

    realItems.forEach((realItem, index) => {
        if (index !== 0) {
            realItem.startTime = new Date(realItems[index - 1].endTime);
            const endTime = new Date(new Date(realItem.startTime));
            endTime.setMinutes(endTime.getMinutes() + realItem.durationEstimated);
            realItem.endTime = endTime;
        } else {
            realItem.startTime = new Date(realItem.startTime);
            const endTime = new Date(new Date(realItem.startTime));
            endTime.setMinutes(endTime.getMinutes() + realItem.durationEstimated);
            realItem.endTime = endTime;
        }
    });
    

    接下来我遍历 breakItems 并检查项目的 endTime 是否 >= break 的开始时间。在这种情况下,我会在第一次响应之后遍历所有项目,并将中断的持续时间添加到项目的 startTime/endTime 中。

    for (const breakItem of breakItems) {
        const breakStart = new Date(breakItem.startTime).getTime();
        for (let x = 0; x < realItems.length; x++) {
            const realItem = realItems[x];
            const realEnd = new Date(realItem.endTime).getTime();
    
            if (realEnd >= breakStart + realItem.durationEstimated * 60000) {
                const items = realItems.slice(x, realItems.length);
                for (const item of items) {
                    item.startTime = new Date(item.startTime);
                    item.startTime.setMinutes(item.startTime.getMinutes() + breakItem.durationEstimated);
                    item.startTime = item.startTime;
                    item.endTime = new Date(item.endTime);
                    item.endTime.setMinutes(item.endTime.getMinutes() + breakItem.durationEstimated);
                    item.endTime = item.endTime;
                }
                break;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      • 2014-02-18
      • 1970-01-01
      • 2019-12-24
      • 2014-12-07
      • 1970-01-01
      相关资源
      最近更新 更多