Javascript 如何获得两个日期范围数组之间的差异?

Javascript 如何获得两个日期范围数组之间的差异?,javascript,date-range,Javascript,Date Range,我有两个日期范围数组,试图找出它们之间的差异。 让我们以数字为例: 我有两个范围[1-7,9-16],我想减去[2-3,7-9,14-20] 并得到[1-1,4-6,10-13] 我想弄清楚这件事,却有点墨守成规。肯定有一个我不知道的共同解决方案 diffDateRangesArray(rangesArray1, rangesArray2) { //rangesArray = [{startDate, endDate}] let diffedRanges = []; ra

我有两个日期范围数组,试图找出它们之间的差异。 让我们以数字为例:

我有两个范围
[1-7,9-16]
,我想减去
[2-3,7-9,14-20]
并得到
[1-1,4-6,10-13]

我想弄清楚这件事,却有点墨守成规。肯定有一个我不知道的共同解决方案

diffDateRangesArray(rangesArray1, rangesArray2) {
    //rangesArray = [{startDate, endDate}]
    let diffedRanges = [];
    rangesArray1.forEach(function(range1){
      //loop through rangesArray2 removing from range1
      rangesArray2.forEach(function(range2){
        // breaks if array returned
        // perhaps should always return array and flatten?
        range1 = diffDateRanges(range1, range2);
      });
      diffedRanges.push(range1);
    });
    //probably should do some sort of union here
    return diffedRanges;
  }

  diffDateRanges(range1, range2) {
    //range = {startDate, endDate}
    let diffedRange = {};
    // if not in range
    if(range2.endDate <= range1.startDate || range2.startDate >= range1.endDate){
      return range1;
    //if envelops range
    } else if(range2.endDate >= range1.endDate && range2.startDate <= range1.startDate){
      return null;
    //if cuts off end of range
    } else if(range2.startDate <= range1.endDate && range2.endDate >= range1.endDate){
      return {startDate:range1.startDate, endDate: range2.startDate};
    // if cuts off start of range
    } else if(range2.endDate >= range1.startDate && range2.startDate <= range1.startDate){
      return {startDate:range2.endDate, endDate: range1.endDate};
    // if inside of range - should better handle arrays
    } else if(range2.startDate >= range1.startDate && range2.endDate <= range1.endDate){
      return [
        {startDate:range1.startDate, endDate: range2.startDate},
        {startDate:range2.endDate, endDate: range1.endDate},
      ];
    }
  }
diffDateRangesArray(RangeSarray 1,RangeSarray 2){
//rangesArray=[{startDate,endDate}]
让diffedRanges=[];
rangesArray1.forEach(函数(range1){
//在Range2中循环从range1中删除
rangesArray2.forEach(函数(range2){
//如果返回数组,则中断
//也许应该总是返回数组并展平?
range1=diffDateRanges(range1,range2);
});
推压(范围1);
});
//也许应该在这里建立某种联盟
回报率差;
}
diffDateRanges(范围1、范围2){
//范围={startDate,endDate}
设diffedRange={};
//如果不在范围内
如果(range2.endDate=range1.endDate){
返回范围1;
//if包络范围

}否则,如果(range2.endDate>=range1.endDate&&range2.startDate=range1.startDate&&range2.startDate=range1.startDate&&range2.endDate如果我正确理解了您的问题,您可以通过以下操作完成您想要的任务:

让我们先做一些实用函数:

function range(start, end) {
  return [...Array(end - start + 1)].map((_, i) => start + i)
}

function unique(a) {
  return Array.from(new Set(a))
}

function immutableSort(arr) {
  return arr.concat().sort((a, b) => a - b)
}

Array.prototype.has = function(e) {
  return this.indexOf(e) >= 0
}

Object.prototype.isEmpty = function() {
  return Object.keys(this).length === 0 && this.constructor === Object
}

function arrayDifference(A, B) {
  return A.filter((e) => B.indexOf(e) < 0)
}
因此,您的问题的答案是:

function yourAnswer(A, B) {
  return arrayToRangeObjects(
    arrayDifference(rangeObjectsToRange(A), rangeObjectsToRange(B))
  )
}
让我们测试一下:

const A = [
  {
    start: 1,
    end: 7
  },
  {
    start: 9,
    end: 16
  }
]

const B = [
  {
    start: 2,
    end: 3
  },
  {
    start: 7,
    end: 9
  },
  {
    start: 14,
    end: 20
  }
]

> yourAnswer(A, B)
[
  {
    start: 1,
    end: 1
  },
  {
    start: 4,
    end: 6
  },
  {
    start: 10,
    end: 13
  }
]

正如我个人的观点,我认为您的“范围对象”数据结构有点难以使用,而且有点不灵活(为了得到与范围集合不重叠的范围而进行的所有这些麻烦):您可能想看看。

因此,这被称为区间代数,并且有一些库用于此

我不知道从
[1-7,9-16]
中减去
[2-3,7-9,14-20]
会导致
[1-1,4-6,10-13]
…你能更详细地解释一下这部分吗,从什么东西中减去什么吗?怎么样:我有数字
[1,2,3,4,5,6,7,9,10,11,12,13,14,16]
,我想删除
[2,3,7,8,9,14,15,16,17,18,19,20]
,导致
[1,4,5,6,10,11,12,13]
-但是输入和输出需要是一个带有
{start,end}
的对象,而不是一个序列。这可能给了我一个想法……我想我只需要翻译
{start,end}< /代码>对象到一个数组中并对它们进行区别,然后将其转换为<代码> {开始,结束} /代码> Arayi将考虑编写一个帮助函数,比如…<代码>函数重叠(快乐,不高兴){if(happy.start你不会有一个关于如何使用r-树的例子吧?@RyanKing我认为你在回答中引用的这个库可以做你想做的事情,如果你考虑间隔的话。非常好的API:
sub
ToObject
…我喜欢它。
const A = [
  {
    start: 1,
    end: 7
  },
  {
    start: 9,
    end: 16
  }
]

const B = [
  {
    start: 2,
    end: 3
  },
  {
    start: 7,
    end: 9
  },
  {
    start: 14,
    end: 20
  }
]

> yourAnswer(A, B)
[
  {
    start: 1,
    end: 1
  },
  {
    start: 4,
    end: 6
  },
  {
    start: 10,
    end: 13
  }
]