聲明:本文爲www.cnc6.cn原創,轉載時請註明出處,謝謝!數據庫
1、第一種用法:數組
public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector);
官方釋義:將序列的每一個元素投影到 IEnumerable<TResult> 並將結果序列合併爲一個序列。函數
廢話很少說,直接Post上代碼:this
1,編寫Person類:spa
class Person { public string Name { set; get; } public int Age { set; get; } public string Gender { set; get; } public Dog[] Dogs { set; get; } }
2,編寫Dog類:3d
public class Dog { public string Name { set; get; } }
請注意:在Person類裏有一個Dog數組,用於存儲實例化Person類所擁有的全部Dog集合,這裏就是SelectMany的關鍵。code
三、編寫客戶端試驗代碼:對象
List<Person> personList = new List<Person> { new Person { Name = "P1", Age = 18, Gender = "Male", Gogs = new Dog[] { new Dog { Name = "D1" }, new Dog { Name = "D2" } } }, new Person { Name = "P2", Age = 19, Gender = "Male", Gogs = new Dog[] { new Dog { Name = "D3" } } }, new Person { Name = "P3", Age = 17,Gender = "Female", Dogs = new Dog[] { new Dog { Name = "D4" }, new Dog { Name = "D5" }, new Dog { Name = "D6" } } } }; var dogs = personList.SelectMany(p => p.Dogs); foreach (var dog in dogs) { Console.WriteLine(dog.Name); }
在這裏咱們定義了由Person構成的List列表,並使用集合及對象初始化器初始化了一些數據。blog
在這裏,SelectMany的做用就是:將personList集合對象的每一個元素(每一個Person實例對象,如名爲「P1」,「P2」,「P3」)索引
映射到每一個Person類對應的Dog集合(如名爲「P1」對應Dog名爲D1及D2的Dog集合),
並將每一個Person類對應Dog的集合從新組合成一個大的Dog集合。
所以,以上將會輸出如下結果:
實際以上的SelectMany對應的LINQ語句爲:
var dogs = from p in personList from d in p.Dogs select d;
咱們能夠將其代替試試就知道結果。
二、第二種用法:
public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector);
官方釋義:將序列的每一個元素投影到 IEnumerable<TResult>,並將結果序列合併爲一個序列。每一個源元素的索引用於該元素的投影表。
其實,就是比第一種使用方法多一個索引而已,該索引是從0開始,針對的是TSource指定類型的集合,最大索引值爲TSource個數-1。
咱們將第一種客戶端試驗代碼中的
var dogs = personList.SelectMany(p => p.Dogs);
修改成
var dogs = personList.SelectMany((p, i) => p.Dogs.Select( d=> { d.Name = $"{i},{d.Name}"; return d; }));
以上方法僅僅是把索引值加到Dog類的Name屬性上。
由以上能夠看到,共有3個Person,所以,索引值最大爲2,每一個Person類有多少個Dog(如名爲P1的Person類,共有2個Dog),
對應的索引就被使用了多少次數(如名爲P1的Person類,索引0被使用了2次),
輸出結果以下:
3、第三種用法:
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);
官方釋義:將序列的每一個元素投影到 IEnumerable<TCollection>,並將結果序列合併爲一個序列,並對其中每一個元素調用結果選擇器函數。
這個用法,跟第一種用法相比,就是能夠對已合成一個大集合的每一個元素調用結果選擇器,返回本身想要的集合類型。
編寫客戶端試驗代碼:
List<Person> personList = new List<Person> { new Person { Name = "P1", Age = 18, Gender = "Male", Gogs = new Dog[] { new Dog { Name = "D1" }, new Dog { Name = "D2" } } }, new Person { Name = "P2", Age = 19, Gender = "Male", Gogs = new Dog[] { new Dog { Name = "D3" } } }, new Person { Name = "P3", Age = 17,Gender = "Female", Gogs = new Dog[] { new Dog { Name = "D4" }, new Dog { Name = "D5" }, new Dog { Name = "D6" } } } }; var results = personList.SelectMany(p => p.Dogs, (p, d) => new { PersonName = p.Name, DogName = d.Name }); foreach (var result in results) { Console.WriteLine($"{result.PersonName},{result.DogName}"); }
關於SelectMany的用法說明以下:
第一個參數:p=>p.Dogs,p指定是想要處理的每一個Person對象,而p.Dogs則是想讓p實例映射的Dog集合;
第二個參數:(p, d) => new { PersonName = p.Name, DogName = d.Name },p與d分別指定是映射後(其實有點相似數據庫的CROSS JOIN)的person實例與dog實例,
如名爲P1的Person類,其Dogs名爲D1及D2,那麼p與d就是:P1/D1,P1/D2(指定是名稱),處理其餘Person類也是如此。而new { PersonName = p.Name, DogName = d.Name }則是返回的一個由本身定義的匿名類型。
結果輸出以下:
實際以上的SelectMany對應的LINQ語句爲:
var results = from p in personList from d in p.Dogs select new { PersonName = p.Name, DogName = d.Name };
4、第四種用法:
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);
官方釋義:將序列的每一個元素投影到 IEnumerable<TCollection>,並將結果序列合併爲一個序列,並對其中每一個元素調用結果選擇器函數。每一個源元素的索引用於該元素的中間投影表。
其實,就是比第三種使用方法多一個索引而已,該索引是從0開始,針對的是TSource指定類型的集合,最大索引值爲TSource個數-1。
咱們將第三種客戶端試驗代碼中的
var results = personList.SelectMany(p => p.Dogs, (p, d) => new { PersonName = p.Name, DogName = d.Name });
修改成
var results = personList.SelectMany((p,i) => { for(int j=0;j<p.Dogs.Length;j++) { p.Dogs[j].Name = $"{i}-{p.Dogs[j].Name}"; } return p.Dogs; }, (p, d) => new { PersonName = p.Name, DogName = d.Name });
以上方法僅僅是把索引值加到Dog類的Name屬性上,並將Dog集合返回。
由以上能夠看到,共有3個Person,所以,索引值最大爲2,每一個Person類有多少個Dog(如名爲P1的Person類,共有2個Dog),
對應的索引就被使用了多少次數(如名爲P1的Person類,索引0被使用了2次),
輸出結果以下: