计算两个时间范围数组(具有时刻范围)

时间:2017-04-05 10:59:35

标签: javascript ecmascript-6 momentjs

我有两个moment-ranges数组,代表两个人忙碌的时期。

计算包含繁忙的联合时间范围的数组的最佳方法是什么?如果两个忙碌时期重叠,我需要时间范围代表他们忙碌的整个时期。

以下是一个例子:

const firstBusyPeriods = [ 
  { start: "2017-04-05T10:00:00Z", end: "2017-04-05T12:00:00Z" },
  { start: "2017-04-05T14:00:00Z", end: "2017-04-05T15:00:00Z" }
]

const secondBusyPeriods = [
  { start: "2017-04-05T08:00:00Z", end: "2017-04-05T11:00:00Z" },
  { start: "2017-04-05T16:00:00Z", end: "2017-04-05T17:00:00Z" }
]

生成的数组应如下所示:

const result = [
  { start: "2017-04-05T08:00:00Z", end: "2017-04-05T12:00:00Z" },
  { start: "2017-04-05T14:00:00Z", end: "2017-04-05T15:00:00Z" },
  { start: "2017-04-05T16:00:00Z", end: "2017-04-05T17:00:00Z" }
]

结果包含重叠繁忙期的联合,然后包括个人之间不重叠的两个期间。

最好是连接两个数组,对结果数组进行排序,还是应用reduce函数?

或者最好是递归迭代两个数组中的一个并生成一个带有并集和非交叉句点的堆栈?

1 个答案:

答案 0 :(得分:2)

我想我会选择concatreduce

const firstBusyPeriods = [{
    start: "2017-04-05T10:00:00Z",
    end: "2017-04-05T12:00:00Z"
  },
  {
    start: "2017-04-05T14:00:00Z",
    end: "2017-04-05T15:00:00Z"
  }
];

const secondBusyPeriods = [{
    start: "2017-04-05T08:00:00Z",
    end: "2017-04-05T11:00:00Z"
  },
  {
    start: "2017-04-05T16:00:00Z",
    end: "2017-04-05T17:00:00Z"
  }
];

const isBetween = function(range, date) {
  return range.start < date && range.end > date;
};

const rangesOverlap = function(rangeOne, rangeTwo) {
  return isBetween(rangeOne, rangeTwo.start) || isBetween(rangeOne, rangeTwo.end);
};

const mergeRanges = function(rangeOne, rangeTwo) {
  let newRange = {}

  if (isBetween(rangeOne, rangeTwo.start)) {
    newRange.start = rangeOne.start;
  } else {
    newRange.start = rangeTwo.start;
  }
  if (isBetween(rangeOne, rangeTwo.end)) {
    newRange.end = rangeOne.end;
  } else {
    newRange.end = rangeTwo.end;
  }

  return newRange;
};

const merge = function(rangeCollectionOne, rangeCollectionTwo) {
  let concatenatedCollections = rangeCollectionOne.concat(rangeCollectionTwo).sort((a,b) => a.start - b.start);
  let newCollection = concatenatedCollections.reduce((newCollection, range) => {
    let index = newCollection.findIndex(rangeToCheck => rangesOverlap(rangeToCheck, range));
    if (index !== -1) {
      newCollection[index] = mergeRanges(newCollection[index], range);
    } else {
      newCollection.push(range);
    }
    return newCollection;
  }, []);

  return newCollection;
}

console.log(merge(firstBusyPeriods, secondBusyPeriods));

首先我尝试使用标准循环方法,我认为这里的递归甚至不需要完成任务。恕我直言reduceconcat方式更优雅。