在集群项目上工作时,我偶然发现了这个问题,我想弄清楚是否有一个比我想出的更好的解决方案。
问题:给定R ^ n中的List<Point> Points
个点(您可以将每个点视为维数n的双数组),double minDistance
和距离Func<Point,Point,double> dist
,写一个LINQ表达式,根据dist,为每个点返回列表中比minDistance更接近他的其他点的集合。
我的解决方案如下:
var lst = Points.Select(
x => Points.Where(z => dist(x, z) < minDistance)
.ToList() )
.ToList();
所以,在注意到
之后我有以下问题:
答案 0 :(得分:3)
问题定义,你想要“为每一点,一组其他点”使得没有内部查询就无法解决 - 你可以巧妙地伪装它。如果您可以更改数据存储策略,并且不遵守LINQ,那么通常会有很多Nearest Neighbour Search问题的方法。例如,您可以根据它们在一个轴上的值来保存点,这可以通过在没有完全距离计算的情况下消除早期的一些候选来加速对邻居的查询。以下是使用此方法的论文:Flexible Metric Nearest Neighbor Classification。
答案 1 :(得分:0)
因为Points
是List
,您可以利用您可以通过索引访问每个项目的事实。因此,您可以避免将每个项目与以下内容进行两次比较:
var lst =
from i in Enumerable.Range(0, Points.Length)
from j in Enumerable.Range(i + 1, Points.Length - i - 1)
where dist(Points[i], Points[j]) < minDistance
select new
{
x = Points[i], y = Points[j]
};
这将返回一个由彼此minDistance
内的所有点组成的集合,但不完全是您想要的结果。如果你想将它变成某种Lookup
,那么你可以看到哪些点接近给定点你可以这样做:
var lst =
(from i in Enumerable.Range(0, Points.Length)
from j in Enumerable.Range(i + 1, Points.Length - i - 1)
where dist(Points[i], Points[j]) < minDistance
select new { x = Points[i], y = Points[j] })
.SelectMany(pair => new[] { pair, { x = pair.y, y = pair.x })
.ToLookup(pair => pair.x, pair => pair.y);
答案 2 :(得分:0)
我认为你可以在你的Property
课程中添加一些bool Point
来标记它已被浏览以防止两次调用dist
,如下所示:
public class Point {
//....
public bool IsBrowsed {get;set;}
}
var lst = Points.Select(
x => {
var list = Points.Where(z =>!z.IsBrowsed&&dist(x, z) < minDistance).ToList();
x.IsBrowsed = true;
return list;
})
.ToList();