c# - 分组和求和
问题描述
我有一个如下列表,其中将包含以下 poco 类。
public class BoxReportView
{
public DateTime ProductionPlanWeekStarting { get; set; }
public DateTime ProductionPlanWeekEnding { get; set; }
public string BatchNumber { get; set; }
public string BoxRef { get; set; }
public string BoxName { get; set; }
public decimal Qty { get; set; }
public FUEL_KitItem KitItem { get; set; }
public decimal Multiplier { get; set; }
}
我想通过使用 BoxName 和 Qty 对报告进行分组并求和所以我尝试了以下
var results = from line in kitItemsToGroup
group line by line.BoxName into g
select new BoxReportView
{
BoxRef = g.First().BoxRef,
BoxName = g.First().BoxName,
Qty = g.Count()
};
在我的旧报告中,我只是这样做
var multiplier = finishedItem.SOPOrderReturnLine.LineQuantity -
finishedItem.SOPOrderReturnLine.StockUnitDespatchReceiptQuantity;
foreach (KitItem kItem in kitItems.Cast<KitItem().Where(z => z.IsBox == true).ToList())
{
kittItemsToGroup.Add(new BoxReportView() {
BatchNumber = _batchNumber,
ProductionPlanWeekEnding = _weekEndDate,
ProductionPlanWeekStarting = _weekStartDate,
BoxRef = kItem.StockCode,
KitItem = kItem,
Multiplier = multiplier,
Qty = kItem.Qty });
}
}
然后我刚回来
return kitItemsToGroup;
但是当我将它用作 var 时,我无法通过框名和数量来处理分组和总和的最佳方法。
解决方案
这是否是最好的方法取决于您的优先级。处理速度重要,还是代码易于理解、易于测试、易于更改和易于调试更重要?
LINQ 的优点之一是,它尽量避免不必要地枚举源。
您确定此代码的用户将始终需要完整的集合吗?会不会是现在,或者在不久的将来,有人只想要第一个元素?还是在他获取第 20 个元素并发现没有任何感兴趣的内容后决定停止枚举?
使用 LINQ 时,尽量返回IEnumerable<...>
。只有将解释您的 LINQed 数据的最终用户决定他是否只想获取FirstOrDefault()
、 或Count()
所有内容,或者将其放入字典中,或其他任何内容。如果不将其用作列表,则创建列表是浪费处理能力。
你的 LINQ 代码和你的 foreach 做一些完全不同的事情。唉,在 StackOverflow 上,人们在没有真正指定他们的要求的情况下要求 LINQ 语句是很常见的。所以我必须在你的 LINQ 语句和你的 foreach 之间猜测一些东西。
需求将 的输入序列分组kitItems
,期望将它们Fuel_KitItems
分成BoxReportViews
具有相同 的组,并从每组中的每个中BoxName
选择几个属性。Fuel_KitItem
var kitItemGroups = kitItems
.Cast<Fuel_KitItem>() // only needed if kitItems is not IEnumerable<Fuel_KitItem>
// make groups of Fuel_KitItems with same BoxName:
.GroupBy(fuelKitItem => fuelKitItem.BoxName,
// ResultSelector, take the BoxName and all fuelKitItems with this BoxName:
(boxName, fuelKitItemsWithThisBoxName) => new
{
// Select only the properties you plan to use:
BoxName = boxName,
FuelKitItems = fuelKitItemsWithThisBoxName.Select(fuelKitItem => new
{
// Only Select the properties that you plan to use
BatchNumber = fuelKitItem.BatchNumber,
Qty = fuelKitItem.Qty,
...
// Not needed, they are all equal to boxName:
// BoxName = fuelKitItem.BoxName
})
// only do ToList if you are certain that the user of the result
// will need the complete list of fuelKitItems in this group
.ToList(),
});
用法:
var kitItemGroups = ...
// I only need the KitItemGroups with a BoxName starting with "A"
var result1 = kitItemGroups.Where(group => group.BoxName.StartsWith("A"))
.ToList();
// Or I only want the first three after sorting by group size
var result2 = kitItemGroups.OrderBy(group => group.FuelKitItems.Count())
.Take(3)
.ToList();
效率改进:只要您不知道如何使用您的 LINQ,就不要将其设为列表。如果您知道需要 group.FuelKitItems 的计数的可能性很高,则到 ToList
推荐阅读
- php - Codeignitor 错误号:1066“不是唯一的表/别名”
- julia - 为什么 trunc() 不将浮点数转换为整数?
- docker - docker v18.09中docker容器的shm挂载到主机有什么用
- objective-c - 如何比较闭包/块?
- jquery - 通过 Controller 方法的 $request 参数获取 $.ajax 发布的数据
- c++ - 我可以访问我的代码中的调用堆栈吗?
- discord.js - Discord.js - 如何使函数仅每 30 秒运行一次
- python - 在 Tkinter 中完成进程后如何再次启用元素
- python - 返回数字表的函数
- html - 合并实用程序类的宽度和弹性属性