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

时间:2012-05-16 22:26:31

标签: c# linq list median

我有以下Linq查询:

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();

此查询为我提供了一个列表,其中包含每个列表项中的以下元素: 商店,月,年,收入

我最终需要做的是计算每个月所有商店的收入中位数,因此我需要以允许我这样做的方式准备好数据。

我认为有一种方法可能是按月将这个列表分成小列表,但我怀疑这是最有效的解决方案。

有没有人对此有任何想法?

每个需要查看的人的每月销售课程:

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 个答案:

答案 0 :(得分:5)

您可以使用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 :(得分: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});