合并具有重叠值的数组

我使用Node.js (…和underscore.js)

考虑这个数据结构

var numbers = [ [10, 20] [30, 40] [40, 50] [45, 70] ... //Possibly more arrays (always contains two numbers) ] 

numbers包含总是包含数字对的数组。 把这些数字对想象成“开始”和“结束”。 我想要一个以numbers为参数的函数,并循环其内容,如果一对的“开始”数字与前一对的“结束”数字重叠,则这些数组合并成一个。 比如这个:

 var numbers = [ [10, 20] [19, 40] [40, 60] [70, 80] ] 

变成这样:

 var numbers = [ [10, 60] // First, second and third array is merged because of overlapping . [70, 80] ] 

其实,我已经写了一个这样的function很好,但感觉有点笨重。

我很好奇,如果一些JavaScript向导可以炫耀我超级优雅的解决scheme=)。

创build一个空的“结果”数组。 在范围数组上循环,并更改结果的最后一项或将当前范围添加到该范围。

 function merge(ranges) { var result = [], last; ranges.forEach(function (r) { if (!last || r[0] > last[1]) result.push(last = r); else if (r[1] > last[1]) last[1] = r[1]; }); return result; } r = [[10, 20], [19, 40], [40, 60], [70, 80]]; document.write(JSON.stringify(merge(r))); 

我创build了一个你想要的function:

 function merge(arr) { // copy and sort the array var result = arr.slice().sort(function(a, b) { return a[0] > b[0]; }), i = 0; while(i < result.length - 1) { var current = result[i], next = result[i+1]; // check if there is an overlapping if(current[1] >= next[0]) { current[1] = Math.max(current[1], next[1]); // remove next result.splice(i+1, 1); } else { // move to next i++; } } return result; }; 

这个函数可以这样使用:

 var mergedNumbers = merge(numbers); 

DEMO

正如@Brett所说,这可能更适合Code Review (只要确保包含当前的实现)。 如果你在那里发帖,请在这里提一个参考,我会提出我的答案。


假设你的numbers数组已经正确sorting,这个函数应该做你想要的:

 function combine(numbers) { return numbers.reduce(function(combined, next) { if (!combined.length || combined[combined.length-1][1] < next[0]) combined.push(next); else { var prev = combined.pop(); combined.push([prev[0], Math.max(prev[1], next[1])]); } return combined; }, []); } var n = [[10, 20], [19, 40], [40, 60], [70, 80], [75, 76]]; var r = combine(n); document.write('<pre>' + JSON.stringify(r) + '</pre>');