按月份将一个列表拆分为多个 - C#,Linq

3

I have the following Linq query:

List<MonthlySales> monthlySales = (from sale in Sales
                     group sale by new { sale.DateSold.Month, sale.Product.Shop } into ds
                     select new MonthlyTitleSales
                     {
                         Shop = ds.Select(it => it.Product.Shop).FirstOrDefault(),
                         Month = ds.Select(it => it.DateSold.Month).FirstOrDefault(),
                         Year = ds.Select(it => it.DateSold.Year).FirstOrDefault(),
                         USDNumberItemsSold = ds.Where(it => it.USDCut.HasValue).Where(it => it.USDCut != 0).Count(),
                         GBPNumberItemsSold = ds.Where(it => it.GBPCut.HasValue).Where(it => it.GBPCut != 0).Count(),
                         EURNumberItemsSold = ds.Where(it => it.EURCut.HasValue).Where(it => it.EURCut != 0).Count(),
                         USDRevenueTotal = PerformCurrencyConversion(ds.Sum(it => it.USDCut.HasValue ? it.USDCut.Value : 0), 0M, 0M, Currency, endDate),
                         GBPRevenueTotal = PerformCurrencyConversion(0M, ds.Sum(it => it.GBPCut.HasValue ? it.GBPCut.Value : 0), 0M, Currency, endDate),
                         EURRevenueTotal = PerformCurrencyConversion(0M, 0M, ds.Sum(it => it.EURCut.HasValue ? it.EURCut.Value : 0), Currency, endDate),
                     }).OrderBy(it => it.DateSold.Month).ToList();

这个查询给我一个列表,每个列表项包含以下元素:商店、月份、年份、收入。
我最终需要做的是计算每个月所有商店收入的中位数,因此我需要准备好这些数据以便于这样做。
我认为一种方法可能是按月份将此列表分成小列表,但我对此是否是最有效的解决方案有所疑虑。
有人对此有什么想法吗?
Monthly Sales类供任何需要查看的人使用:
public class MonthlySales
    {
        public int Month { get; set; }
        public int Year { get; set; }

        public Shop Shop { get; set; }

        public int USDNumberItemsSold { get; set; }
        public int GBPNumberItemsSold { get; set; }
        public int EURNumberItemsSold { get; set; }
        public int TotalNumberItemsSold { get { return USDNumberItemsSold + GBPNumberItemsSold + EURNumberItemsSold; } }

        public decimal USDRevenueTotal { get; set; }
        public decimal GBPRevenueTotal { get; set; }
        public decimal EURRevenueTotal { get; set; }
        public decimal OverallEarnings { get { return USDRevenueTotal + GBPRevenueTotal + EURRevenueTotal; } }
    }
2个回答

6
您可以使用 GroupBy 将列表按月份分组。例如,下面的代码将按月份(实际上是月份+年份)进行分组,然后将每个月的所有值写出到控制台:
var grouped = monthlySales.GroupBy(ms => string.Format("{0}-{1}", ms.Month, ms.Year));

foreach(var group in grouped)
{
     Console.WriteLine("Values in month-year of {0}:", group.Key);
     foreach(var ms in group)
         Console.WriteLine("   {0}", ms.USDRevenueTotal);
}

1

GroupBy非常适合解决这个问题。还要考虑使用ToLookup(您可以使用相同的代码,只需将GroupBy更改为ToLookup)。

区别:

  • GroupBy是惰性的。
  • ToLookup是急切的。

  • 由于GroupBy的惰性特性,它依赖于源数据的存在才能产生结果。如果源数据发生变化,GroupBy的结果也会随之改变 - 它是连接的。
  • 而ToLookup由于其急切的特性,不在乎源数据是否发生变化或消失 - 它是断开的。

  • GroupBy 返回一个 IEnumerable<IGrouping<TKey, TValue>>,仅适用于循环遍历。
  • ToLookup 返回一个 ILookup<TKey, TValue>,类似于 Dictionary<TKey, List<TValue>>,支持按键查找,同时也是一个 IEnumerable<IGrouping<TKey, TValue>>

此外,考虑使用字符串以外的键的替代方案。以下是一个匿名类作为键:
var grouped = monthlySales.GroupBy(ms => new {ms.Month, ms.Year}); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接