const a = [[1, 3], [7, 9], [12, 18]];
const b = [[2, 3], [4,5], [6,8], [13, 14], [16, 17]];
const rangeToArr = ([start, end]) => Array.from({ length: end - start + 1 }, (_, i) => start + i);
const flat = inputArr => inputArr.reduce((arr, elm) => arr.concat(...elm), []);
const aRange = flat(a.map(rangeToArr));
const bRange = flat(b.map(rangeToArr));
const intersection = aRange.filter(num => bRange.includes(num));
console.log(intersection);
// Have the intersection of elements
// now we have to turn the intersection back into an array of ranges again:
const { partialIntersectionRange, thisRangeStarted, lastNum }
= intersection.reduce(({ partialIntersectionRange, thisRangeStarted, lastNum }, num) => {
// Initial iteration only: populate with initial values
if (typeof thisRangeStarted !== 'number') {
return { partialIntersectionRange, thisRangeStarted: num, lastNum: num };
}
// If this element is a continuation of the range from the last element
// then just increment lastNum:
if (lastNum + 1 === num) {
return { partialIntersectionRange, thisRangeStarted, lastNum: num };
}
// This element is not a continuation of the previous range
// so make a range out of [thisRangeStarted, lastNum] and push it to the range array
// (in case thisRangeStarted === lastNum, only push a single value)
if (thisRangeStarted !== lastNum) partialIntersectionRange.push([thisRangeStarted, lastNum]);
else partialIntersectionRange.push([thisRangeStarted]);
return { partialIntersectionRange, thisRangeStarted: num, lastNum: num };
}, { partialIntersectionRange: [] });
if (thisRangeStarted !== lastNum) partialIntersectionRange.push([thisRangeStarted, lastNum]);
else partialIntersectionRange.push([thisRangeStarted]);
console.log(JSON.stringify(partialIntersectionRange));