1. 程式人生 > 其它 >程式碼乾貨——C#Linq表示式按周、旬、季、年聚類投影寫法

程式碼乾貨——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替代了具體的返回值。 周分組 同樣地,旬產量的分析稍微有一點不同,那就是區分出每個旬的天數,當然一個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(); 旬分組 對於季產量,假如月資料已經按生產日期進行排序之後獲得了月資料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(); 季分組 年產量沒有直接拿出資料庫的欄位值,同樣也是使用分組的方式,這裡把程式碼附上(原理都一樣): 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的相關用法,如果您點進來請給筆者一個贊或者評論以示鼓勵,你們的鼓勵是我更新下去的動力。