结合两个简单的相关linq查询

时间:2011-02-25 02:07:52

标签: c# linq

我有两个查询,我正在使用第二个中的第一个结果,如此

 var temp  = (ObjectTable.Where(o => o.Category == "Y"));
 var anonymousObjList = temp.Select(o => new {o, IsMax = (o.Value == temp.Max(x => x.Value))});

有没有办法将这些组合成一个查询?

编辑: 我不能直接链接它们,因为我在第二个查询中使用temp.Max()。

3 个答案:

答案 0 :(得分:5)

为什么呢?将它变为三个会更清晰(也更有效率):

var temp  = (ObjectTable.Where(o => o.Category == "Y"));
int max = temp.Max(x => x.Value);
var anonymousObjList = temp.Select(o => new {o, IsMax = (o.Value == max)});

答案 1 :(得分:1)

可能最直接的重构是用temp的值替换所有“temp”实例。由于看起来这个值是不可变的,因此重构应该是有效的(但是很难看):

var anonymousObjList = ObjectTable.Where(o => o.Category == "Y")
    .Select(o => new {o, IsMax = (o.Value == ObjectTable.Where(o => o.Category == "Y").Max(x => x.Value))});

正如已经指出的那样,这个查询确实没有优势,因为查询使用了deffered执行并且可以构建。我实际上建议更多地分割查询

var temp  = (ObjectTable.Where(o => o.Category == "Y")); 
var maxValue = temp.Max(x => x.Value);    
var anonymousObjList = temp.Select(o => new {o, IsMax = (o.Value == maxValue)});

比原始更好,因为每次调用“Max”都会导致对整个数据集进行另一次迭代。由于它是在原始选择中调用的,因此被调用了n次。这使得原始的O(n ^ 2)!

答案 2 :(得分:1)

可以使用let关键字使用查询语法在一个语句中执行此操作。它只评估'max'一次,所以它就像三个单独的语句一样,只在一行中。

var anonymousObjList = from o in ObjectTable
                       where o.Category == "Y"
                       let max = ObjectTable.Max(m => m.Value)
                       select new { o, IsMax = (o.Value == max) };

这是我唯一一次使用查询语法。你不能使用方法语法来做到这一点!

编辑:ReSharper建议

var anonymousObjList = ObjectTable.Where(o => o.Category == "Y")
    .Select(o => new {o, max = ObjectTable.Max(m => m.Value)})
    .Select(@t => new {@t.o, IsMax = (@t.o.Value == @t.max)});
然而,这不是最佳的。第一个Select为ObjectTable中的每个项目投射max属性 - 将为每个项目评估Max函数。如果使用查询语法,则只评估一次。

同样,您只能使用查询语法执行此操作。我不是查询语法的粉丝,但这使它值得,而且是我使用它的唯一情况。 ReSharper错了。