假設我有一個如下所示的陣列,如果時間重疊,最好的方法是將它們分成單獨的陣列嗎?我正在使用時刻,但有點不確定如何解決這個問題。
我知道我最初必須對陣列進行排序。
資料:
const timetable = [
{ class: 'one', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
{ class: 'two', start: '2021-11-16T010:00:00', end: '2021-11-16T11:00:00' },
{ class: 'three', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
];
預期的:
const timetable = [
[
{ class: 'one', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
{ class: 'two', start: '2021-11-16T010:00:00', end: '2021-11-16T11:00:00' },
],
[
{
class: 'three',
start: '2021-11-16T09:00:00',
end: '2021-11-16T10:00:00',
},
],
];
uj5u.com熱心網友回復:
通用方法必須通過任何給定的原始timetable(源陣列)遞回地作業,以便檢測/生成盡可能多的時間表,每個時間表僅具有不重疊的時間范圍專案。
只要在已處理的陣列中仍然存在重疊的時間范圍項,遞回實作就會重復呼叫自身。
方法的一部分是,這樣的自遞回函式確實創建了傳遞時間表的淺表副本,并且在最初被呼叫時確實對其進行了一次排序。
function parseTime(value) {
return new Date(value).getTime();
}
function getParsedTimeRangeFromItem({ start, end }) {
return {
start: parseTime(start),
end: parseTime(end),
}
}
function orderByTimeRangeAscending(a, b) {
const { start: aStart, end: aEnd } = getParsedTimeRangeFromItem(a);
const { start: bStart, end: bEnd } = getParsedTimeRangeFromItem(b);
return (aStart - bStart) || (aEnd - bEnd);
}
function createTimetablesOfNonOverlappingTimeRanges(timetable, result) {
// at initial call time only ...
if (!Array.isArray(result)) {
// ... create the result array ...
result = [];
// ... and also a shallow and sorted copy
// of the initially passed `timetable`.
timetable = [...timetable].sort(orderByTimeRangeAscending);
}
const rejected = [];
let idx = -1;
let item, nextItem;
while (
(item = timetable[ idx]) &&
(nextItem = timetable[idx 1])
) {
// detect `nextItem` as overlapping time range item ...
if (parseTime(item.end) > parseTime(nextItem.start)) {
// ... and reject it from the `timetable` reference.
rejected.push(timetable.splice((idx 1), 1)[0])
--idx;
}
}
// add the sanitized but mutated `timetable` to `result`.
result.push(timetable);
// in case of any rejected time range item trigger self recursion.
if (rejected.length >= 1) {
result =
createTimetablesOfNonOverlappingTimeRanges(rejected, result);
}
return result;
}
const timetable = [
{ class: 'one', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
{ class: 'two', start: '2021-11-16T10:00:00', end: '2021-11-16T11:00:00' },
{ class: 'three', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
{ class: 'four', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
{ class: 'five', start: '2021-11-16T10:00:00', end: '2021-11-16T11:00:00' },
{ class: 'six', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
];
console.log(
'[...timetable].sort(orderByTimeRangeAscending) ...',
[...timetable]
.sort(orderByTimeRangeAscending)
);
console.log(
'createTimetablesOfNonOverlappingTimeRanges(timetable) ...',
createTimetablesOfNonOverlappingTimeRanges(timetable)
);
console.log('un-mutated original source array ...', { timetable });
.as-console-wrapper { min-height: 100%!important; top: 0; }
uj5u.com熱心網友回復:
把它分解成更小的塊并解決每個問題。如果您最終有多個重疊的課程,我不確定您的計劃是什么。這段代碼只回傳一個包含兩個元素的陣列:唯一類和重疊類,它不會繼續為每個違規類添加新元素。
const timetable = [
{ class: "one", start: "2021-11-16T09:00:00", end: "2021-11-16T10:00:00" },
{ class: "two", start: "2021-11-16T10:00:00", end: "2021-11-16T11:00:00" },
{ class: "three", start: "2021-11-16T09:00:00", end: "2021-11-16T10:00:00" },
];
// get an object, return a new object with the times as
// timestamps, rather than time strings
// (you don't need Moment.JS, JavaScript has .getTime())
const parseTimes = el => {
const hour = {...el};
hour.start = new Date(el.start).getTime();
hour.end = new Date(el.end).getTime();
return hour;
};
// given two objects, see if one is fully before or after
// another. If not, they overlap.
const overlaps = (a, b) => {
if (a.start <= b.start && a.end <= b.start) return false;
if (a.end >= b.end && a.start >= b.end) return false;
return true;
};
// given an array and a starting place, figure out if any
// of the objects overlap any of the previous objects
const overlapsPrevious = (arr, idx) => {
const a = parseTimes(arr[idx]);
for (let ix = 0; ix <= idx; ix ) {
const b = parseTimes(arr[ix]);
if (a.class !== b.class && overlaps(a, b)) return true;
}
return false;
};
// given an array, return a new array with non-overlaping
// objects and objects that overlap
const split = (arr) => {
const unique = [];
const overlap = [];
for(let ix = 0; ix < arr.length; ix ) {
if(overlapsPrevious(arr, ix)) overlap.push(arr[ix]);
else unique.push(arr[ix]);
}
return [unique, overlap];
}
// display the result
console.log(split(timetable));
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/407405.html
標籤:
