我相信问题很明确。它在给定的垂直边缘范围数组中请求不相交的交叉点。这意味着
[[10, 100], [50, 120], [60, 180], [140, 220]]
array 为我们提供了两个不相交的交集,一个来自[10, 100], [50, 120], [60, 180],得到[60,100],另一个来自[60, 180], [140, 220]],得到[140,180]。因此,当您注意到生成的交叉点 [60,100] 和 [140,180] 时,从这组给定的垂直边获得的交叉点是不相交的。
在JS中实现这个功能的一种方式如下;
function getDisjointedIntersections(a){
var di;
return a.reduce((p,c,i,a) => c.used ? p
: (p.push(a.map((_,j) => a[(i+j)%a.length])
.reduce((s,e) => (di = [Math.max(s[0],e[0]), Math.min(s[1],e[1])],
di[0] < di[1] ? (e.used = true, di) : s))),p),[]);
}
var regions = [[10, 100],[50, 120],[60, 180],[140, 220],[150, 330]];
console.log(getDisjointedIntersections(regions));
解释:起初很容易将这项工作视为一项简单的还原工作,但我想并非如此。在某些情况下,您应该考虑之前的垂直边缘,因此可能需要多次通过。
所以我们将从给定的数组开始,并开始尽可能地将我们的垂直边缘减少到它们的交点。这样做时,每条导致成功相交的垂直边都将被分配一个名为used 的属性,其值为true。完成此过程后,我们将向上旋转输入数组,直到未使用的垂直边缘到达索引位置 0 并再次开始通过交集减少垂直边缘,但这次是从以前未使用的项目开始。
所以代码的核心,交叉点reducer是
.reduce((s,e) => (di = [Math.max(s[0],e[0]), Math.min(s[1],e[1])],
di[0] < di[1] ? (e.used = true, di) : s))
这是一个没有首字母的简单化简。它首先将交集分配给di。
di = [Math.max(s[0],e[0]), Math.min(s[1],e[1])]
然后如果交集成功,则将当前元素标记为已使用并返回di,这将是下一个reduce循环的前一个元素。如果交集不成功,则将之前的交集返回到下一个reduce循环。
di[0] < di[1] ? (e.used = true, di) : s))
好的,我们已经完成了一个循环,只有[10, 100], [50, 120], [60, 180] 相交并产生[60,100]。所以我们把这个结果推到外部reduce初始数组中。
(p.push(a.map((_,j) => a[(i+j)%a.length])
.reduce((s,e) => ... // the code that we already know
但是,我们将 reduce 链接到的 map 函数是什么。每次外部 reduce 的迭代,map 将我们的输入数组旋转一个索引。好的,看看它,你就会明白它是如何工作的
a.reduce((p,c,i,a) => c.used ? p
: (p.push(a.map((_,j) => a[(i+j)%a.length])
.redu...
但您也会注意到,我们并没有进行浪费的轮换。我们首先等到外部 reduce 的当前元素 (c) 遇到未使用的项目。只有这样我们才旋转输入数组以形成我们的新输入数组。例如,我们必须在此示例中处理的两个输入数组是。
[ [ 10, 100 ],[ 50, 120 ],[ 60, 180 ],[ 140, 220 ],[ 150, 330 ] ]
和
[ [ 140, 220 ],[ 150, 330 ],[ 10, 100, used: true ],[ 50, 120, used: true ],[ 60, 180, used: true ] ]
因此,在这种特殊情况下,只需两次通过即可将所有垂直边标记为已使用,并为我们提供所有两个不连接的交叉点...无论您对输入数组进行多少次混洗。
它在 15~16 毫秒内计算 1000 条输入数据,在大约 400-500 毫秒内计算 10000 条输入数据。您可以检查代码并使用参数here
好的,以下版本已修改为仅显示允许大小的不相交交叉点。您可能想尝试here 以获得不同数量的垂直边、轴大小和不相交交叉点的最小大小。
function getDisjointedIntersections(a,n){
var di, // disjointed intersections
ri; // resulting intersections
return a.reduce(function(p,c,i,a){
if (c.used) return p;
ri = a.map((_,j) => a[(i+j)%a.length])
.reduce(function(s,e){
di = [Math.max(s[0],e[0]), Math.min(s[1],e[1])];
return di[0] < di[1] ? (e.used = true, di) : s;
});
ri[1] - ri[0] > n && p.push(ri);
return p;
},[]);
}
var regions = [[10, 100],[50, 120],[60, 180],[140, 220],[150, 330]];
console.log(getDisjointedIntersections(regions,20));