分组和总和

时间:2019-03-05 15:13:05

标签: c# linq

我有一个如下列表,其中包含以下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 SO进行总结

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时,我无法以最好的方式来处理按框名称和数量进行分组和的总和。

1 个答案:

答案 0 :(得分:3)

这是否是最好的方法取决于您的优先级。处理速度重要吗?或者易于理解,易于测试,易于更改和调试的代码更重要?

LINQ的优点之一是,它试图避免不必要地枚举源。

您确定此代码的用户将始终需要完整的集合吗?是现在还是在不久的将来,有人只想要第一个要素?还是在他获取了第20个元素并发现对他没有兴趣后决定停止枚举?

使用LINQ时,请尝试尽可能长的返回IEnumerable<...>。仅让将解释您的LINQed数据的最终用户决定他是否只希望使用FirstOrDefault()Count()一切,或将其放入词典中,或其他。如果不将其用作列表,则浪费创建列表的处理能力。

您的LINQ代码和您的foreach做一些完全不同的事情。 Stack,这在StackOverflow上非常普遍,人们无需真正指定他们的要求就可以请求LINQ语句。因此,我将不得不猜测您的LINQ语句和您的foreach之间的某些情况。

要求kitItems的输入序列(应为Fuel_KitItems分组为具有相同BoxReportViews的{​​{1}}组,并从每个组的每个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(),
         });

效率改进::只要您不知道如何使用LINQ,就不要将其列为列表。如果您知道需要使用group.FuelKitItems的Count的可能性很高,则将其添加到ToList