2017-04-05 76 views
1

我有两个数组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" } 
] 

结果包含重叠忙周期的结合,并且然后包括两个时期,唐” t在个体之间重叠。

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

或者最好是递归迭代两个数组中的一个,并产生一个带有union和非相交周期的堆栈?

+0

答案很好,这里有一个类似的问题,应该很容易修改:http://stackoverflow.com/a/32770846/1075247 – Pureferret

回答

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方式更优雅。