У меня есть массив перекрывающихся диапазонов:
var ranges = [{
"from": 0,
"to": 100
}, {
"from": 50,
"to": 200
}, {
"from": 0,
"to": 100
}, {
"from": 70,
"to": 200
}, {
"from": 90,
"to": 300
}];
Мне нужно преобразовать его в набор непересекающихся диапазонов, т.е. э.:
var nonOverlapping = splitRanges(ranges);
/*
nonOverlapping = [{
"from": 0,
"to": 49
}, {
"from": 50,
"to": 69
}, {
"from": 70,
"to": 89
}, {
"from": 90,
"to": 100
}, {
"from": 101,
"to": 200
}, {
"from": 201,
"to": 300
}]
*/
Я сделал функцию, которая делает это (в JavaScript), но, конечно, как вы можете видеть, она работает очень медленно, потому что использует так называемый «наивный подход»:
function splitRanges(ranges) {
var repeat, length, i, j;
var rangeA, rangeB, intersection;
do {
repeat = false;
length = ranges.length;
for (i = 0; i < length; i++) {
rangeA = ranges[i];
for (j = i + 1; j < length; j++) {
rangeB = ranges[j];
if (isIntersectingRanges(rangeA, rangeB)) {
repeat = true;
ranges.splice(i, 1);
intersection = splitRange(rangeA, rangeB);
while (intersection.length) {
ranges.push(intersection.shift());
}
}
if (repeat) break;
}
if (repeat) break;
}
} while (repeat);
}
Может ли кто-нибудь помочь мне переписать это, чтобы оно вело себя так же и делало это быстрее, чем наивный подход?
ИЗМЕНИТЬ:
Алгоритм должен иметь возможность отслеживать идентификаторы диапазонов + правильно обрабатывать диапазоны, где от == до:
var ranges = [{
id: 1,
from: 0,
to: 100
}, {
id: 2,
from: 30,
to: 30,
}, {
id: 3,
from: 0,
to: 100
}, {
id: 4,
from: 90,
to: 300
}];
Ожидаемый результат:
[{
"id": 3,
"from": 90,
"to": 100
}, {
"id": 4,
"from": 90,
"to": 100
}, {
"id": 4,
"from": 101,
"to": 300
}, {
"id": 1,
"from": 0,
"to": 29
}, {
"id": 1,
"from": 90,
"to": 100
}, {
"id": 3,
"from": 0,
"to": 29
}, {
"id": 1,
"from": 30,
"to": 30
}, {
"id": 1,
"from": 31,
"to": 89
}, {
"id": 2,
"from": 30,
"to": 30
}, {
"id": 3,
"from": 30,
"to": 30
}, {
"id": 3,
"from": 31,
"to": 89
}]