在lambda表达式链语法中加入List <array>

时间:2016-07-27 15:41:26

标签: c# arrays linq list lambda

我是Joins的业余爱好者,但我正在尝试使用表达式链式语法而不是LINQ语句。我发现的大多数示例都使用了数组或类列表{List <class&gt; };但没有任何数组列表{List <array&gt; }

List<int[]> needHelp = new List<int[]>{ 
new int[3] { 10, 20, 50},
new int[3] { 10, 21, 53},
new int[3] { 10, 22, 55},
new int[3] { 11, 20, 60},
new int[3] { 11, 22, 51} };

List<int[]> ghosts = new List<int[]>{ 
new int[3] { 10, 45, 65},
new int[3] { 11, 34, 60} };

有效的LINQ“查询”语法是:

List<int[]> result = (from h in needHelp join g in ghosts on h[0] equals g[0] 
                      where h[1] == 21 select g).ToList();

但是这个“方法”表达式链接语法对我不起作用:

List<int[]> result = needHelp.Join(ghosts, x=>x[0], y=>y[0], (x,y) => y ).Where(x => x[1] == 21).ToList();

对于那些感兴趣的人,我发现这个lambda表达式链可以打印出一个数组List,而不必使用两个foreach循环。

result.ForEach( x => { Array.ForEach(x, e => Console.Write(e + " ") ); Console.WriteLine();} );

好吧我认为我找到了自己的解决方案,而且是通过更改where子句的位置。但是,何时必须在加入之前到来而不是之后工作?我在帖子上看到如果这是一个数据库调用where类在“.Join”之前,那么它将在服务器而不是客户端上处理。我假设在加入之后尝试使用它是超出的数据范围,在这个例子中将是y(列表<int[]&gt;鬼魂)。

3 个答案:

答案 0 :(得分:1)

JoinWhere一般不可互换。

如果你“大声”阅读你的表达链,它会读到这样的内容:首先让我ghosts中的所有数组与needHelp中的第一个元素匹配,然后选择那些第二个元素等于21 的数组。

因此,在Join之后,您只剩下来自ghosts列表的数组。您的WHERE子句则不返回任何内容,因为ghosts中的任何内容都没有第二个元素等于21.您正在needHelp列表中检查它。

我建议您切换JoinWhere

List<int[]> result = needHelp.Where(x => x[1] == 21).Join(ghosts, x=>x[0], y=>y[0], (x,y) => y ).ToList();

如果它是您的混淆源,请不要认为函数中的xy变量意味着多个函数的任何内容。您的Where来电与x needHelp有关,但这并不意味着x函数中的JoinneedHelp相关;它引用Where的输出,它是来自ghosts的元素。

答案 1 :(得分:0)

您的Join方法不是您提供的查询语法的翻译。

您的查询过滤了h[1](加入时为x[1]),但您只选择y(查询中为g),以便后面的地方适用于错误的事情。

以下是您的查询的直接翻译:

List<int[]> result = 
    needHelp
    .Join (ghosts, x => x[0], y => y[0], (x, y) => new { x, y })
    .Where (anon => anon.x[1] == 21)
    .Select (anon => anon.y)
    .ToList ();

答案 2 :(得分:0)

与此查询语法等效的确切方法语法

from h in needHelp join g in ghosts on h[0] equals g[0] 
where h[1] == 21
select g

是这样的:

needHelp.Join(ghosts, h => h[0], g => g[0], (h, g) => new { h, g })
    .Where(x => x.h[1] == 21)
    .Select(x => x.g);

查询语法使用所谓的“透明标识符”来隐藏那些中间匿名类型,这就是为什么更适合涉及连接的查询。

谈到连接以及一般情况下,IMO最好在加入之前应用过滤器,尤其是在LINQ to Objects中,因为数据库查询优化器无论如何都会重新排列过滤器和连接操作。因此,更好的查询(来自性能和内存分配)将是:

needHelp.Where(h => h[1] == 21).Join(ghosts, h => h[0], g => g[0], (h, g) => g);