我有一個區間陣列,另一個區間定義為范圍。目標是創建一個陣列陣列,其中包含所有不重疊但在定義范圍內的間隔的開始和結束編號。
最初的用途是我有一個服務器,它服務于數十萬個物件,這些物件的時間戳彼此相距一秒。可以使用任意兩個時間戳發出請求,因此我需要存盤來自服務器的查詢物件,下次使用兩個不同時間戳發出請求時,僅查詢丟失的物件。這個問題使用小數字來簡化事情。
輸入:
const intervals = [
[3, 5],
[7, 9],
];
const range = [2, 11];
在這種情況下的輸出將是 [[2, 3], [5, 7], [9, 11]]
間隔始終按開始日期排序,并且輸入間隔永遠不會重疊,因為合并和排序是在此之前完成的,根據此答案https://stackoverflow.com/a/67717721/13585195
我已經設法針對這種特定情況提出了解決方案,但是在嘗試涵蓋其他情況時會出現問題,例如:
- 輸入: 間隔:
[[3, 5]];范圍:[4, 8];輸出:[[5, 8]] - 輸入: 間隔:
[[7, 11]];范圍:[2, 8];輸出:[[2, 7]] - 輸入: 間隔:
[[3, 5], [6, 8]];范圍:[4, 7];輸出:[[5, 6]] - 輸入: 間隔:
[[5, 10], [15, 20], [25, 30]];范圍:[0, 35];輸出:[[0, 5], [10, 15], [20, 25], [30, 35]]
我現在擁有的代碼檢查所需范圍是否已經在快取中,以及它是否與快取日期部分重疊:
const partiallyCached = cachedDates.some(
(cachedDate) =>
range.start.getTime() <= cachedDate.end.getTime() &&
cachedDate.start.getTime() <= range.end.getTime()
);
if (partiallyCached) {
console.log("Partially cached, merging query");
const queryRange = functionToFindNonOverlappingIntervalsInRange(cachedDates, range);
const newCachedDates = mergeOverlappingDateRanges([...cachedDates, range]);
return {
cache: newCachedDates,
queryRange,
};
}
我還想知道我是否應該繼續撰寫if陳述句來縮小上述每個案例的范圍,并為每個案例撰寫一個單獨的函式,或者是否可以撰寫一個解決所有案例的函式。
uj5u.com熱心網友回復:
您可以獲取 range 的起始值并檢查間隔并構建一個新陣列。
const
getInbetween = (intervals, range) => {
const
result = [];
let value = range[0],
index = 0;
while (value < range[1] && index < intervals.length) {
let [left, right] = intervals[index];
if (value < left) result.push([value, left]);
value = right;
index ;
}
if (value < range[1]) result.push([value, range[1]]);
return result;
};
console.log(getInbetween([[3, 5], [7, 9]], [2, 11]));
console.log(getInbetween([[3, 5], [7, 9]], [4, 11]));
console.log(getInbetween([[3, 5], [7, 9]], [4, 8]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
uj5u.com熱心網友回復:
假設這是已排序的,并且所有區間都已合并,那么只需要考慮幾種情況。
- 范圍的開始在第一個元素之前。
- 范圍的起點與第一個元素相交。
- 范圍的末尾與最后一個元素相交。
- 范圍的結尾超過了最后一個元素。
- 一個元素位于范圍的開始和結束之內。
function getNonOverlappingIntervals(intervals, [rangeStart, rangeStop]) {
const output = [];
let prevStop = null;
const intervalsInRange = intervals.filter(([start, stop]) => {
if (rangeStart <= start && rangeStop >= stop) return true;
if (start < rangeStart && stop > rangeStart) return true;
if (start < rangeStop && stop > rangeStop) return true;
return false;
});
// check if rangeStart precedes first interval
if (intervalsInRange[0][0] > rangeStart) {
output.push([rangeStart, intervalsInRange[0][0]]);
prevStop = intervalsInRange[0][1];
} else if (intervalsInRange[0][0] < rangeStart) {
prevStop = intervalsInRange[0][1];
}
// iterate intervals and compare against last checked interval
if (intervalsInRange.length > 2) {
for (let i = 1; i < intervalsInRange.length; i ) {
output.push([prevStop, intervalsInRange[i][0]]);
prevStop = intervalsInRange[i][1];
}
}
// check if rangeStop exceeds last interval
if (intervalsInRange[intervalsInRange.length - 1][1] < rangeStop) {
output.push([intervalsInRange.at(-1)[1], rangeStop]);
}
return output;
}
console.log(getNonOverlappingIntervals([[3, 5],[7, 9]], [2, 11]));
console.log(getNonOverlappingIntervals([[3, 5]], [4, 8]));
console.log(getNonOverlappingIntervals([[7, 11]], [2, 8]));
console.log(getNonOverlappingIntervals([[3, 5], [6, 8]], [4, 7]));
console.log(getNonOverlappingIntervals([[5, 10], [15, 20], [25, 30]], [0, 35]));
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/395563.html
標籤:javascript 数组 日期 间隔 日期范围
