在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
原文链接 https://www.e-learn.cn/content/net/1318737 一、第一种用法: public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector); 官方释义:将序列的每个元素投影到 IEnumerable<TResult> 并将结果序列合并为一个序列。 废话不多说,直接Post上代码: 1,编写Person类: class Person { public string Name { set; get; } public int Age { set; get; } public string Gender { set; get; } public Dog[] Dogs { set; get; } } 2,编写Dog类: public class Dog { public string Name { set; get; } } 请注意:在Person类里有一个Dog数组,用于存储实例化Person类所拥有的所有Dog集合,这里就是SelectMany的关键。 3、编写客户端试验代码: 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列表,并使用集合及对象初始化器初始化了一些数据。 在这里,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; 我们可以将其代替试试就知道结果。 2、第二种用法: 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次), 输出结果如下: 三、第三种用法: 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 }; 四、第四种用法: 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次), 输出结果如下: |
请发表评论