2017-04-05 13 views
1

moment-rangesという2つの配列があり、2人のユーザーがビジー状態になっている期間を表します。時間範囲の2つの配列からのユニオン時間範囲を計算します。

混雑している時間帯が含まれている配列を計算するには、どのような方法が最適ですか? 2つのビジー期間が個人にとって重複している場合は、ビジー期間全体を表す時間範囲が必要です。ここで

は例です:

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

結果が重複忙しい期間の労働組合が含まれ、その後、ドン」は2つの期間を含んでいます個体間で重複する。

2つの配列を連結し、結果の配列をソートし、reduce関数を適用するのが最善でしょうか?

または、2つの配列の1つを再帰的に反復し、結果として結合および非交差の期間を持つスタックを生成するのが最善でしょうか?

+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));

まず私は、標準的なループ・アプローチで試してみました、私は、再帰はここでもタスクを達成するために必要とされていないと思います。 IMHO reduceconcat方法はよりエレガントです。

関連する問題