2017-04-05 113 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方式更優雅。