我从后端收到这样的数组:
[
{index: 0, start: '07:00', end: '09:00'},
{index: 1, start: '09:00', end: '11:00'},
{index: 0, start: '12:00', end: '15:00'},
]
为了更好地使用它,我决定尝试将其转换为如下形式:
// this is array1
[
{index: 0, time: startInMilliseconds},
{index: 1, time: startInMilliseconds}, // no difference between 0's end and 1's start, no no null here
{index: null, time: endInMilliseconds},
{index: 0, time: startInMilliseconds},
{index: null, time: endInMilliseconds}
]
因为我需要能够像这样插入和替换间隔:如果我用start: '08:00'
和end: '08:30'
插入对象,则应该将第一个间隔分成两部分。如果start: '10:00'
和end: '12:30'
,则前一个间隔应该在10:00结束,下一个间隔应该在12:30开始,并且它们之间的空白时间段应该消失。
当前,在按时间对对象进行排序之后,我正在尝试使用for循环和许多if
来做到这一点,就像这样:
intervals.push(
{index: index, time: startInMilliseconds, new: true},
{index: null, time: endInMilliseconds, new: true}
);
intervals.sort((a,b) => {
if(a.time < b.time) return -1;
if(a.time > b.time) return 1;
if(!a.new && b.new) return -1;
if(a.new && !b.new) return 1;
return 0;
});
for(let i=0, iStart=null, lastIndex=null; i<intervals.length; i++){
if(intervals[i].time == startInMilliseconds){
if(intervals[i].new){
if(intervals[i-1] && intervals[i-1].index == intervals[i].index){
iStart = i-1;
intervals.splice(i, 1);
i--;
}else{
iStart = i;
delete intervals[i].new;
}
}else{
intervals.splice(i, 1);
i--;
}
continue;
}
if(iStart != null && intervals[i].time <= endInMilliseconds && !intervals[i].new){
lastIndex = intervals[i].index;
intervals.splice(i, 1);
i--;
continue;
}
if(iStart != null && intervals[i].time == endInMilliseconds && intervals[i].new){
if(lastIndex == intervals[iStart].index) intervals.splice(i, 1);
else{
intervals[i].index = lastIndex;
delete intervals[i].new;
}
break;
}
}
这显然很难遵循并且不能完全起作用,但是我想不出另一种方法。我也不知道该如何正确地向Google描述。
以下是一些示例,用于说明执行某些操作后array1的外观。假设字符串是以毫秒为单位的时间:
// insert {index: 2, start: '08:00', end: '08:30'}
[
{index: 0, time: '07:00'},
{index: 2, time: '08:00'},
{index: 0, time: '08:30'},
{index: 1, time: '09:00'},
{index: null, time: '11:00'},
{index: 0, time: '12:00'},
{index: null, time: '15:00'}
]
// insert {index: 2, start: '10:00', end: '12:30'}
[
{index: 0, time: '07:00'},
{index: 1, time: '09:00'},
{index: 2, time: '10:00'},
{index: 0, time: '12:30'},
{index: null, time: '15:00'}
]
// insert {index: 1, start: '10:00', end: '12:30'}
[
{index: 0, time: '07:00'},
{index: 1, time: '09:00'},
{index: 0, time: '12:30'},
{index: null, time: '15:00'}
]
答案 0 :(得分:0)
我不得不重构您的代码,以下使用原始数组格式和间隔的顺序处理。希望评论足够。
我将时间减少到几分钟,您可以使用任何喜欢的常见因素,只需将 timeToMins 函数替换为任何合适的函数即可。它还删除了减少到零时间的间隔,即开始和结束是相同的。假定间隔已排序且有效,即值,开始<结束,范围不重叠(但插入的间隔可以与现有间隔重叠)等。
分割范围时,它使用Object.assign复制当前间隔,该间隔适用于简单对象,但是如果对象更复杂,则需要更好的东西。
// Convert time in HH:mm to minutes
function timeToMins(time) {
let [h, m] = time.split(':');
return h*60 + m*1;
}
function insertInterval(arr, nInterval) {
var nStart = timeToMins(nInterval.start);
var nEnd = timeToMins(nInterval.end);
var inserted = false;
var temp;
// Insert after current if after true, otherwise before
function insert(after) {
if (!inserted) {
arr.splice(i + Number(!!after), 0, nInterval);
inserted = true;
i++;
}
}
for (var i=0; i<arr.length; i++) {
let cInterval = arr[i];
let cStart = timeToMins(cInterval.start);
let cEnd = timeToMins(cInterval.end);
// Cases where new start <= current start
if (nStart <= cStart) {
// If before first or between another range
if (nEnd <= cStart) {
insert();
return;
// If overlaps start only
} else if (nEnd <= cEnd) {
insert();
cInterval.start = nInterval.end;
// If overlaps end too, remove current
} else if (nEnd >= cEnd) {
insert();
arr.splice(i, 1);
--i;
}
// cases where new start > current start
} else { // if (nStart > cStart) {
// If starts in the range
if (nStart < cEnd) {
insert(true);
temp = cInterval.end; // Remember end in case it's needed below
cInterval.end = nInterval.start;
}
// If also ends in the range, need to split range
if (nEnd < cEnd) {
insert(true);
var tail = Object.assign({}, cInterval);
tail.start = nInterval.end;
tail.end = temp;
arr.splice(++i, 0, tail);
}
}
// If cInterval is now of zero length, remove it
if (cInterval.start == cInterval.end) {
arr.splice(i, 1);
--i;
}
}
// If didn't get inserted, must be after last
if (!inserted) arr.push(nInterval);
}
// Examples
var data = [
{index: 0, start: '07:00', end: '08:00'}, // 0
{index: 1, start: '09:00', end: '10:00'}, // 1
{index: 0, start: '10:00', end: '11:00'} // 2
];
// Some interesting cases, there are many more to test...
[ {index: 1, start: '07:05', end:'07:15'}, // Splits first
{index: 1, start: '08:05', end:'08:15'}, // Between 0 & 1
{index: 0, start: '09:30', end: '10:15'} // Overlaps 1 end & 2 start
].forEach( interval => {
insertInterval(data, interval);
console.log(data.map(a=>JSON.stringify(a)).join('\n'));
});