Объединить перекрывающиеся диапазоны дат - PullRequest
0 голосов
/ 30 марта 2020

Как я могу объединить перекрывающиеся диапазоны дат в массиве?

У меня есть массив дат:

const dates = [
  {startDate: "2020-03-19T00:00:00+01:00", endDate: "2020-03-20T00:00:00+01:00"},
  {startDate: "2020-03-09T00:00:00+01:00", endDate: "2020-03-16T00:00:00+01:00"},
  {startDate: "2020-02-07T00:00:00+01:00", endDate: "2020-03-09T00:00:00+01:00"},
  {startDate: "2020-02-07T00:00:00+01:00", endDate: "2020-02-13T00:00:00+01:00"}
];

То, что я ищу для достижения sh, это иметь перекрывающиеся массивы слились так, что я получил бы в результате:

//Result I'm looking for:
const mergedDates = [
  {startDate: "2020-03-19T00:00:00+01:00", endDate: "2020-03-20T00:00:00+01:00"},
  {startDate: "2020-02-07T00:00:00+01:00", endDate: "2020-03-16T00:00:00+01:00"}
];

Я использую moment-range для создания диапазонов:

const ranges = dates.map(d => {
  return moment.range(d.startDate, d.endDate);
});

Тогда я Я использую два for цикла для определения перекрытия

  let arrRange = [];

  for (let i = 0; i < ranges.length; i++) {
    const el1 = ranges[i];
    let loop=[];
    for (let i = 0; i < ranges.length; i++) {
      const el2 = ranges[i];
      const overlaps = el1.overlaps(el2, { adjacent: true });
      if(overlaps){
        loop = [...loop, i]
      }
    }
    arrRange.push(loop);
  }
}

Это дает мне массив, в котором у меня есть массивы индексов, поэтому я знаю, где находятся перекрытия:

console.log(arrRange);
// [[0], [1, 2], [1, 2, 3], [2, 3]]

Однако я застрял.

Даже зная наложения, я не могу понять, как их объединить.

1 Ответ

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

Я бы использовал Math.min и Math.max для получения первой и последней конечных точек даты для каждого перекрывающегося диапазона, а затем уменьшал бы каждый индексный массив до объединенного объекта диапазона:

const merged = arrRange.map(idxArray => {
  const { min, max } = idxArray.reduce(({ min, max }, index) => {
    const range = ranges[index];
    return {
      min: Math.min(min, range.start.toDate()),
      max: Math.max(max, range.end.toDate())
    };
  }, { min: Number.MAX_VALUE, max: Number.MIN_VALUE }); // throwaway value
  return moment.range(new Date(min), new Date(max));
});
...