代码干货——C#Linq表达式按周、旬、季、年聚类投影写法

转载自:https://blog.csdn.net/qq_37036915/article/details/113728952

 

C#中Linq表达式使用场景(聚类,投影写法) 该项目主要解决石油产量的分析工作,数据库中存了石油产量的日和月数据,其中月数据中包含了年数据的字段和值,因此按日产量、月产量、年产量分析计算不存在什么问题。但项目中需求累计周产量、旬产量、季产量进行分析,这样的需求怎么解决呢? 一般来说有两种解决方案: 将日产量数据获取出来,然后按照日期进行排序,然后对于日产量进行foreach循环,周产量每七天相加可得,但旬产量分为上旬、中旬、下旬,这样对于上旬、中旬来说都是10天,下旬就是每个月的天数减去20天,按照这样的方式进行循环相加,这样做的弊端就是代码不好写且不易控制,代码可读性不佳。笔者并不推荐这种做法,当然大神除外哈。这样就催生了第二种解决方案,使用linq表达式可以很好地将其解决。 使用Linq表达式 假如日数据已经按生产日期进行排序之后获得了日数据list——WellsProdsDay.那么我们首先通过GroupBy()方法进行对周进行分组,代码为: this.WellsProdsDay.GroupBy(x => x.ProdDate.AddDays(-(int)x.ProdDate.DayOfWeek)) prodDate即为每日的生产日期,类型为DateTime类型,于是我们对于周产量的字段写一个bean类,名为WellProdWeekDescriptor,假如这个bean类里定义了周产油量、周产水量(在此只举这两个字段为例)于是可以利用Select方法进行向新表投影,于是代码为:  
var wellsProdsWeek = this.WellsProdsDay.GroupBy(x => x.ProdDate.AddDays(-(int)x.ProdDate.DayOfWeek))
.Select(item => new WellProdWeekDescriptor{ //周产油 WeekOil = item.Sum(y => y.DailyOil), //周产水 WeekWater = item.Sum(y => y.DailyWater)}).ToList();

 

在select方法中提供了Sum()即为求和,Average()方法求平均值,这些可以自己试用,在此只提供Linq写法,最后ToList()方法将新表进行封装,其返回值为List,但为了方便写,C#提供了var替代了具体的返回值。   代码干货——C#Linq表达式按周、旬、季、年聚类投影写法   周分组 同样地,旬产量的分析稍微有一点不同,那就是区分出每个旬的天数,当然一个GroupBy()是不够的,但是我已经写好了获取旬天数的工具方法,在此先展示出旬的工具方法代码:   /// /// 获取指定年,指定月, 指定旬的开始日期 /// /// 年 /// 月 /// 日 /// 日期 public static DateTime GetStartOfTen(int year, int month, int ten) { if (!IsValidYear(year)) { throw new ArgumentOutOfRangeException("Valid values are 0-9999, and your transfer value is" + year); } if (!IsValidMonth(month)) { throw new ArgumentOutOfRangeException("Valid values are 1-12, and your transfer value is" + month); } if (!IsValidTen(ten)) { throw new ArgumentOutOfRangeException("Valid values are 1-3, and your transfer value is" + ten); } if (ten == 1) { return new DateTime(year, month, 1, 0, 0, 0, 0); } else if (ten == 2) { return new DateTime(year, month, 11, 0, 0, 0, 0); } else { return new DateTime(year, month, 21, 0, 0, 0, 0); } }   使用GroupBy()方法对日产量进行分组,代码为: var wellsProdXun = this.WellsProdsDay.GroupBy(x => GetStartOfTen(x.ProdDate)) 其中表达式中调用了GetStartOfTen()方法,根据日期自动分出上旬,中旬、下旬的组别。然后通过Select()方法进行投影,旬产量类名为WellProdXunDescriptor。代码为: var wellsProdXun = this.WellsProdsDay.GroupBy(x => GetStartOfTen(x.ProdDate)).Select(item => new WellProdXunDescriptor{ //旬产油 XunOil = item.Sum(y => y.DailyOil), //旬产水 XunWater = item.Sum(y => y.DailyWater)}).ToList();   代码干货——C#Linq表达式按周、旬、季、年聚类投影写法 旬分组 对于季产量,假如月数据已经按生产日期进行排序之后获得了月数据list——WellMonProdData.那么我们首先通过GroupBy()方法进行对季进行分组,代码为: var wellSeasonProdData = this.WellMonProdData.GroupBy(x => x.ProdDate.AddMonths(0 - (x.ProdDate.Month - 1) % 3).AddDays(1 - x.ProdDate.Day)) 通过Select()方法进行投影,季产量类名为WellProdSeasonDescriptor,代码为: var wellSeasonProdData = this.WellMonProdData.GroupBy(x => x.ProdDate.AddMonths(0 - (x.ProdDate.Month - 1) % 3).AddDays(1 - x.ProdDate.Day)).Select(item => new WellProdSeasonDescriptor{ //季产油 SeasonOil = item.Sum(y => y.MonthlyOil), //季产水 SeasonWater = item.Sum(y => y.MonthlyWater)}).ToList();   代码干货——C#Linq表达式按周、旬、季、年聚类投影写法 季分组 年产量没有直接拿出数据库的字段值,同样也是使用分组的方式,这里把代码附上(原理都一样): var wellYearProdData = this.WellMonProdData.GroupBy(x => x.ProdDate.AddMonths(-(x.ProdDate.Month - 1)).AddDays(1 - x.ProdDate.Day)).Select(item => new WellProdYearDescriptor{ //年产油 YearOil = item.Sum(y => y.MonthlyOil), //年产水 YearWater = item.Sum(y => y.MonthlyWater)}).ToList(); 当然Liuq表达式的强大之处并不局限于此,这只是解决了一个问题的需求,之后有很多地方都用到了Linq表达式的写法,基本很少使用foreach遍历的写法,代码冗长且不易阅读。今天就先分享到这里,接下来还会给大家更新其他的linq表达式以及前端工具包DevExpress的相关用法,如果您点进来请给笔者一个赞或者评论以示鼓励,你们的鼓励是我更新下去的动力。  
上一篇:用group时count和sum


下一篇:Pandas-分组与聚合