简体   繁体   English

Linq加入没有平等

[英]Linq join without equals

I have a list of rectangles and a list of points. 我有一个矩形列表和一个点​​列表。 I want to construct a LINQ query that will match the list of points with their corresponding rectangles. 我想构建一个LINQ查询,它将匹配点列表及其对应的矩形。 Something like this: 像这样的东西:

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

How does one accomplish something like this with LINQ? 如何使用LINQ实现这样的功能?

EDIT: 编辑:

My lists are equal size - I have one point to match with one rectangle, and the rectangles don't overlap. 我的列表大小相同 - 我有一个点与一个矩形匹配,矩形不重叠。

However, the point of the question isn't so much to solve this one specific problem. 然而,问题的关键不在于解决这个具体问题。 I'm interested, in general, how to join two lists on any condition other than simply 'equals'. 一般来说,我感兴趣的是如何在除了'equals'之外的任何条件下加入两个列表。

You can use multiple from clauses to achieve a join 您可以使用多个from子句来实现连接

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

Multiple from clauses are more flexible than the join syntax ( see myth 5 of 10 LINQ myths ). 多个from子句比join语法更灵活( 参见神话中的5个LINQ神话 )。 You need to learn only this one and all joins will be easy. 你只需要学习这一个,所有的连接都很容易。

You can use Enumerable.ToLookup to create a lookup table per rectangle: 您可以使用Enumerable.ToLookup为每个矩形创建一个查找表:

var lookup = points.ToLookup(p => rectangles.First(r => r.Contains(point)));

Using this is similar to a grouping query: 使用它类似于分组查询:

foreach(var group in lookup)
{
    Console.WriteLine("Rectangle {0} contains:", group.Key);
    foreach(var point in group)
        Console.WriteLine("    {0}", point);
}

On a side note - this query is quadratic in nature, and likely to perform poorly with very large datasets. 在旁注 - 这个查询本质上是二次的,并且可能在非常大的数据集上表现不佳。 If you need to do this for many points and/or many rectangles, you may wish to investigate spatial data structures for quicker lookups. 如果需要对许多点和/或许多矩形执行此操作,您可能希望研究空间数据结构以便更快地查找。 That may not be an issue in this case, however. 然而,在这种情况下,这可能不是问题。

Have you tried just using a where statement, instead of joining them: 您是否尝试过使用where语句,而不是加入它们:

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

There are two ways of getting what you want. 有两种方法可以获得你想要的东西。

points.Select(p => new { Point = p, Rectangles = rectangles.Where(r => r.Contains(p) });

This caters to the case where a point may be in many rectangles. 这适用于点可能在许多矩形中的情况。

points.Select(p => new { Point = p, Rectangle = rectangles.First(r => r.Contains(p) });

This caters to the case where a point is in exactly one rectangle. 这适用于一个点恰好在一个矩形中的情况。

The second case should work best in your scenario. 第二种情况应该在您的方案中最佳。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM