11

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

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

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

编辑:

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

但是,问题的重点并不是解决这一特定问题。一般来说,我感兴趣的是如何在任何条件下加入两个列表,而不是简单地“等于”。

4

4 回答 4

16

您可以使用多个 from 子句来实现连接

 var matches = from p in points
               from r in rectangles
               where r.Contains(p)
               select new { r, p };

多个 from 子句比连接语法更灵活(参见 10 个 LINQ 神话中的 5 个)。你只需要学习这个,所有的连接都会很容易。

于 2012-05-04T20:07:00.780 回答
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);
}

附带说明 - 此查询本质上是二次的,并且可能在非常大的数据集上表现不佳。如果您需要对许多点和/或许多矩形执行此操作,您可能希望研究空间数据结构以便更快地查找。但是,在这种情况下,这可能不是问题。

于 2012-05-04T20:04:40.143 回答
1

您是否尝试过仅使用 where 语句,而不是加入它们:

var matches = from rectangle in rectangles
              from point in points
              where rectangle.Contains(point)
              select new { rectangle, point };
于 2012-05-04T20:08:15.170 回答
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) });

这迎合了一个点正好在一个矩形中的情况。

第二种情况应该最适合您的场景。

于 2012-05-04T20:17:10.550 回答