我有两个linq查询,一个要获取confirmedQty
,另一个要获取unconfirmedQty
。
有获得的条件unconfirmedQty
。它应该是平均值而不是总和。
result = Sum(confirmedQty) + Avg(unconfirmedQty)
有什么方法可以只编写一个查询并获得所需的结果,而不是编写两个单独的查询?
我的密码
class Program
{
static void Main(string[] args)
{
List<Item> items = new List<Item>(new Item[]
{
new Item{ Qty = 100, IsConfirmed=true },
new Item{ Qty = 40, IsConfirmed=false },
new Item{ Qty = 40, IsConfirmed=false },
new Item{ Qty = 40, IsConfirmed=false },
});
int confirmedQty = Convert.ToInt32(items.Where(o => o.IsConfirmed == true).Sum(u => u.Qty));
int unconfirmedQty = Convert.ToInt32(items.Where(o => o.IsConfirmed != true).Average(u => u.Qty));
//Output => Total : 140
Console.WriteLine("Total : " + (confirmedQty + unconfirmedQty));
Console.Read();
}
public class Item
{
public int Qty { get; set; }
public bool IsConfirmed { get; set; }
}
}
实际接受的答案会枚举您的项目收集2N + 1
时间,并且会为您的原始解决方案增加不必要的复杂性。如果我遇到了这段代码
(from t in items
let confirmedQty = items.Where(o => o.IsConfirmed == true).Sum(u => u.Qty)
let unconfirmedQty = items.Where(o => o.IsConfirmed != true).Average(u => u.Qty)
let total = confirmedQty + unconfirmedQty
select new { tl = total }).FirstOrDefault();
需要花费一些时间来了解将项目投影到的数据类型。是的,此查询是一个奇怪的预测。它创建SelectIterator
要投影序列的每个项目,然后创建一些范围变量,其中涉及对项目进行两次迭代,最后选择第一个投影项目。基本上,您已将原始查询包装到其他无用的查询中:
items.Select(i => {
var confirmedQty = items.Where(o => o.IsConfirmed).Sum(u => u.Qty);
var unconfirmedQty = items.Where(o => !o.IsConfirmed).Average(u => u.Qty);
var total = confirmedQty + unconfirmedQty;
return new { tl = total };
}).FirstOrDefault();
意图深深地隐藏在代码中,并且您仍然具有相同的两个嵌套查询。您在这里可以做什么?您可以简化两个查询,使其更具可读性,并清楚地表明您的意图:
int confirmedTotal = items.Where(i => i.IsConfirmed).Sum(i => i.Qty);
// NOTE: Average will throw exception if there is no unconfirmed items!
double unconfirmedAverage = items.Where(i => !i.IsConfirmed).Average(i => i.Qty);
int total = confirmedTotal + (int)unconfirmedAverage;
如果性能比可读性更重要,那么您可以在单个查询中计算总数(出于可读性考虑,移至扩展方法):
public static int Total(this IEnumerable<Item> items)
{
int confirmedTotal = 0;
int unconfirmedTotal = 0;
int unconfirmedCount = 0;
foreach (var item in items)
{
if (item.IsConfirmed)
{
confirmedTotal += item.Qty;
}
else
{
unconfirmedCount++;
unconfirmedTotal += item.Qty;
}
}
if (unconfirmedCount == 0)
return confirmedTotal;
// NOTE: Will not throw if there is no unconfirmed items
return confirmedTotal + unconfirmedTotal / unconfirmedCount;
}
用法很简单:
items.Total();
顺便说一句第二个解决方案,从接受的答案是不正确的。它返回正确的值只是一个巧合,因为所有未确认的项目都具有equal Qty
。此解决方案计算总和而不是平均值。分组的解决方案如下所示:
var total =
items.GroupBy(i => i.IsConfirmed)
.Select(g => g.Key ? g.Sum(i => i.Qty) : (int)g.Average(i => i.Qty))
.Sum();
在这里,您将项目分为两组-已确认和未确认。然后,您可以根据组键以及两个组值的汇总来计算总和或平均值。这也不是可读性也不高效率的解决方案,但这是正确的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句