1

如何在数组上合并重叠的日期范围?

我有一系列日期:

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"}
];

我想要完成的是合并重叠的数组,这样我就会得到:

//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]]

但是,我被困住了。

即使知道重叠,我也不知道如何合并它们。

4

3 回答 3

1

我今天必须这样做(打字稿,但你明白了):

interface DateRange {
  start: Date;
  end: Date;
}
export function mergeOverlappingDateRanges(
  dateRanges: DateRange[],
): DateRange[] {
  const sorted = dateRanges.sort(
    // By start, ascending
    (a, b) => a.start.getTime() - b.start.getTime(),
  );

  const ret = sorted.reduce((acc, curr) => {
    // Skip the first range
    if (acc.length === 0) {
      return [curr];
    }

    const prev = acc.pop();

    if (curr.end <= prev.end) {
      // Current range is completely inside previous
      return [...acc, prev];
    }

    // Merges overlapping (<) and contiguous (==) ranges
    if (curr.start <= prev.end) {
      // Current range overlaps previous
      return [...acc, { start: prev.start, end: curr.end }];
    }

    // Ranges do not overlap
    return [...acc, prev, curr];
  }, [] as DateRange[]);

  return ret;
}
于 2021-05-27T07:40:21.907 回答
0

我将使用Math.minandMath.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));
});
于 2020-03-30T19:32:00.440 回答
0
        var rawArray = [
        { name: 'C', startDate: '2021/02/01', endDate: '2021/02/15' },
        { name: 'A', startDate: '2021/01/01', endDate: '2021/01/15' },
        { name: 'D', startDate: '2021/02/12', endDate: '2021/02/25' },
        { name: 'E', startDate: '2021/02/22', endDate: '2021/02/28' },
        { name: 'F', startDate: '2021/03/01', endDate: '2021/03/15' },
        { name: 'B', startDate: '2021/01/12', endDate: '2021/01/30' },
    ]
    console.log('Input', rawArray)
    
        for (var i = 0; i < rawArray.length; i++) {
            for (var j = i + 1; j < rawArray.length; j++) {
                if (isBetweenOrOverlap(rawArray[i].startDate, rawArray[i].endDate, rawArray[j].startDate, rawArray[j].endDate)) {
                    rawArray[i].startDate = getLeastDate(rawArray[i].startDate, rawArray[j].startDate);
                    rawArray[i].endDate = getMaxDate(rawArray[i].endDate, rawArray[j].endDate);
                    rawArray.splice(j, 1);
                    i = i - 1;
                    break;
                }
            }
        }
    
        console.log('Ouput', rawArray)

Input [
  { name: 'C', startDate: '2021/02/01', endDate: '2021/02/15' },
  { name: 'A', startDate: '2021/01/01', endDate: '2021/01/15' },
  { name: 'D', startDate: '2021/02/12', endDate: '2021/02/25' },
  { name: 'E', startDate: '2021/02/22', endDate: '2021/02/28' },
  { name: 'F', startDate: '2021/03/01', endDate: '2021/03/15' },
  { name: 'B', startDate: '2021/01/12', endDate: '2021/01/30' }
]
Ouput [
  { name: 'C', startDate: '2021/02/01', endDate: '2021/02/28' },
  { name: 'A', startDate: '2021/01/01', endDate: '2021/01/30' },
  { name: 'F', startDate: '2021/03/01', endDate: '2021/03/15' }
]
于 2021-05-01T05:20:14.190 回答