日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Linq下有一个非常实用的SelectMany方法,很多人却不会用

發布時間:2023/12/4 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linq下有一个非常实用的SelectMany方法,很多人却不会用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在平時開發中經常會看到有些朋友或者同事在寫代碼時會充斥著各種for,foreach,這種程式代碼太多的話閱讀性特別差,而且還顯得特別累贅,其實在FCL中有很多幫助我們提高閱讀感的方法,而現實中很多人不會用或者說不知道,這篇我就跟大家聊一聊。

一:SelectMany

這個方法絕對是提高開發速度的一大利器,有太多的業務場景需要使用這個函數,舉一個我實際應用場景,商家按照年份和客戶類型預先設置一些標簽,然后讓系統跑一下它的各自標簽到底有多少人?

1. 定義Model

為了方便演示,這里做了一下簡化代碼,只有一個字典,key表示年份,value:就是該年份的多組標簽。

public class EstimateModel{public int ShopID { get; set; }//key:年份public Dictionary<string, List<TagCrowdFilterModel>> YearCrowdFilterDict { get; set; }}public class TagCrowdFilterModel{/// <summary>/// 篩選條件/// </summary>public string CrowdFiter { get; set; }/// <summary>/// 獲取人數/// </summary>public int TotalCustomerCount { get; set; }}

為了更加清晰,我決定再填充一下數據

public static void Main(string[] args){var estimateModel = new EstimateModel(){ShopID = 1,YearCrowdFilterDict = new Dictionary<string, List<TagCrowdFilterModel>>(){{"17年",new List<TagCrowdFilterModel>(){new TagCrowdFilterModel(){ CrowdFiter="between 10 and 20" },new TagCrowdFilterModel(){ CrowdFiter=" a<10 || a>30" },}},{"18年",new List<TagCrowdFilterModel>(){new TagCrowdFilterModel(){ CrowdFiter="between 100 and 200" },new TagCrowdFilterModel(){ CrowdFiter=" a<100 || a>300" },}},{"19年",new List<TagCrowdFilterModel>(){new TagCrowdFilterModel(){ CrowdFiter="between 1000 and 2000" },new TagCrowdFilterModel(){ CrowdFiter=" a<1000 || a>3000" },}}}};}public static int GetCustomerID(string crowdfilter){return BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0);}

2. 實現需求

需求也很簡單,就是依次獲取 TagCrowdFilterModel 中的 CrowdFiter 字段再調用GetCustomerID方法把人數賦值給TotalCustomerCount即可,這么簡單的需求,如果讓你來搞定,你該怎么實現這個邏輯?沒錯,很多人可能就是兩個foreach搞定。

foreach (var year in estimateModel.YearCrowdFilterDict.Keys){var yearCrowdFitlerList = estimateModel.YearCrowdFilterDict[year];foreach (var crowdFitler in yearCrowdFitlerList){crowdFitler.TotalCustomerCount = GetCustomerID(crowdFitler.CrowdFiter);}}

看似代碼也很清爽,但現實哪有這么好的事情,真實情況是年份上可能還要套上一個客戶類型,客戶類型之上再套一個商品,商品之上再套一個商家,這樣很深的層級你就需要多達3個foreach,4個foreach甚至5個foreach才能搞定,再放張圖給大家看看,是不是看著頭大...????

3. 優化辦法

如果你會selectMany,那只需要一個鏈式寫法就可以搞定,是不是簡單粗暴,雖然性能比不上命令式寫法,但可讀性和觀賞性真的上了幾個檔次。

estimateModel.YearCrowdFilterDict.SelectMany(m => m.Value).ToList().ForEach(m =>m.TotalCustomerCount = GetCustomerID(m.CrowdFiter));

二:原理探究

1. msdn解釋

將序列的每個元素投影到 IEnumerable,并將結果序列合并為一個序列,并對其中每個元素調用結果選擇器函數,鏈接:https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.enumerable.selectmany?view=netframework-4.8 有了上面的案例解釋,再看msdn的這句話,我想你應該徹徹底底的明白了selectMany怎么使用。

2. 翻查源碼

宏觀上明白了,接下來用ILSpy去查下微觀代碼,到底這玩意是怎么實現的。

public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector) {if (source == null){throw Error.ArgumentNull("source");}if (selector == null){throw Error.ArgumentNull("selector");}return SelectManyIterator(source, selector); }private static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector) {foreach (TSource item in source){foreach (TResult item2 in selector(item)){yield return item2;}} }

大家仔細體會下這兩個foreach,尤其是第二個foreach,其中的selector(item)不就是年份下的標簽集合嗎?再遍歷這個集合把每一個item返回出去,返回值是IEnumerable,這得益于yield語法糖,它本質上就是一個編譯器封裝好的迭代類,做到了一個延遲,按需執行,后面我會專門分享一下yield,很有意思????

好了,本篇就說到這里,希望對你有幫助。

總結

以上是生活随笔為你收集整理的Linq下有一个非常实用的SelectMany方法,很多人却不会用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。