我有一个矩形列表和一个点列表。我想构建一个LINQ查询,它将匹配点列表及其对应的矩形。像这样:
// Does not compile
var matches = from rect in rectangles
join point in points on rect.Contains(point)
select new { rect, point };
如何用LINQ完成这样的事情?
编辑:
我的列表大小相同 - 我有一个点与一个矩形匹配,矩形不重叠。
然而,问题的关键不在于解决这个具体问题。一般来说,我感兴趣的是如何在除了'equals'之外的任何条件下加入两个列表。
答案 0 :(得分:14)
您可以使用多个from子句来实现连接
var matches = from p in points
from r in rectangles
where r.Contains(p)
select new { r, p };
多个from子句比连接语法(see myth 5 of 10 LINQ myths)更灵活。你只需要学习这一个,所有的连接都很容易。
答案 1 :(得分:3)
您可以使用Enumerable.ToLookup为每个矩形创建一个查找表:
var lookup = points.ToLookup(p => rectangles.First(r => r.Contains(point)));
使用它类似于分组查询:
foreach(var group in lookup)
{
Console.WriteLine("Rectangle {0} contains:", group.Key);
foreach(var point in group)
Console.WriteLine(" {0}", point);
}
侧面说明 - 此查询本质上是二次的,并且对于非常大的数据集可能表现不佳。如果需要对许多点和/或许多矩形执行此操作,您可能希望研究空间数据结构以便更快地查找。但是,在这种情况下,这可能不是问题。
答案 2 :(得分:1)
您是否尝试过使用where语句,而不是加入它们:
var matches = from rectangle in rectangles
from point in points
where rectangle.Contains(point)
select new { rectangle, point };
答案 3 :(得分:1)
有两种方法可以获得你想要的东西。
points.Select(p => new { Point = p, Rectangles = rectangles.Where(r => r.Contains(p) });
这适用于一个点可能在许多矩形中的情况。
points.Select(p => new { Point = p, Rectangle = rectangles.First(r => r.Contains(p) });
这适用于一个点恰好在一个矩形中的情况。
第二种情况应该在您的方案中效果最佳。