Linq加入没有平等

时间:2012-05-04 19:52:41

标签: c# linq join

我有一个矩形列表和一个点​​列表。我想构建一个LINQ查询,它将匹配点列表及其对应的矩形。像这样:

// Does not compile
var matches = from rect in rectangles
              join point in points on rect.Contains(point)
              select new { rect, point };

如何用LINQ完成这样的事情?

编辑:

我的列表大小相同 - 我有一个点与一个矩形匹配,矩形不重叠。

然而,问题的关键不在于解决这个具体问题。一般来说,我感兴趣的是如何在除了'equals'之外的任何条件下加入两个列表。

4 个答案:

答案 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) });

这适用于一个点恰好在一个矩形中的情况。

第二种情况应该在您的方案中效果最佳。