Массив сортировки (расписание Ганта) по дате + длительность (мин) - с остановками c (дата + длительность) - PullRequest
1 голос
/ 20 марта 2020

У меня есть массив, основанный на графике Ганта. Массив содержит объекты со следующими свойствами

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

и некоторыми значениями generi c. На основании этих значений мне нужно l oop через массив и сортировать / обновлять startTime на основе предыдущих значений. При этом мне также нужно учитывать "isBreak" (stati c value - 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}
] 

Первый элемент (id = '1') будет работать в течение 30 минут. Затем перерыв (id = '2') на 15 минут и затем sh вверх за последние 30 минут до запуска следующего элемента (id = '3') . (Новый элемент никогда не будет добавлен к позиции 0)

Скажем, мне нужно добавить еще один объект в это (время начала не имеет значения)

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

Я помещаю sh в массив в После этого массив будет выглядеть следующим образом:

[ 
    {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 строк и содержит несколько разрывов + различные значения продолжительности. Оценочные значения.

Пробовал

Я всегда сталкиваюсь с проблемами, когда мне приходится перемещать элементы в массиве, чтобы учесть время перерыва.

Я думаю, что я oop через массив, проверяющий каждый элемент, сравнивающий его с предыдущим элементом ( startTime + duration ) и добавляющий новую дату к текущему элементу итерации startTime . И затем go через каждый предмет, делающий это. Проблема в том, что происходят перерывы, видя, что они статичны c и никогда не обновляются.

Это работает, если вы только добавляете новые элементы в последнюю позицию массива ( Потому что мне не нужно сортировать, можно проверить только предыдущее значение). Но в реальном приложении новые предметы будут добавляться в любую позицию.

Ответы [ 2 ]

1 голос
/ 20 марта 2020

Не уверен, как преобразовать его в 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, и это, очевидно, может быть преобразованным во что-то еще. И это, скорее всего, крайне неэффективно, но, вероятно, должно помочь вам.

0 голосов
/ 23 марта 2020

Мне удалось заставить его работать с помощью ответа Torxed.

Сначала ил oop через каждый элемент и установить endTime

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;
});

Далее я отфильтрую действительные * "и ** разбивают элементы на массивы

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

L oop через все realItems

Установите startTime из предыдущих значений endTime

Получить элемент startTime + длительность = 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;
    }
});

Затем выполните il oop через breakItems и проверьте, является ли endTime элемента> = время начала перерыва. В этом случае il oop через все элементы после этого первого ответа, и добавьте продолжительность перерыва к обоим 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;
        }
    }
}
...