using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Xunit; using LinqStudy; namespace LinqStudy.Test.LinqToObject { /// /// 投影操作符 /// 投影:遍历序列中的元素,将元素由一种类型转换为另一种类型的操作,并返回由转换后元素组成的新序列。 /// 即是:IEnumerable => IEnumerable /// public class ProjectiveTest { #region Select /// /// Select投影:简单投影,一对一 /// [Fact] public void Select_Test() { // Arrange var persons = PersonManager.GetPersons(); // Act var maps = persons.Select(p => p.Age).ToList(); // Assert Assert.IsType>(maps); } /// /// 投影为匿名类 /// [Fact] public void Select_Anonymous_Test() { // Arrange var persons = PersonManager.GetPersons(); // Act var maps = persons.Select(p => new { Id = p.Id, Node = $"姓名{p.Name},年龄{p.Age}." }).ToList(); // Assert Assert.IsNotType>(maps); } /// /// 投影传入索引(序号)参数 /// [Fact] public void Select_Index_Test() { var persons = PersonManager.GetPersons(); var maps = persons.Select((query, index) => new KeyValuePair(index, query)).ToList(); var indexs = persons.Select((query, index) => index).ToList(); Assert.IsType>>(maps); Assert.Equal(0, indexs[0]); } #endregion #region SelectMany /// /// 将序列的每个元素投影到 IEnumerable 并将结果序列合并为一个序列。 /// /// /// SelectMany:复合投影,一对多,合并多到一个集合。 /// 枚举源序列,将源序列每一项投影为新的集合,合并所有新集合为一个可枚举序列,做为返回值; /// 提供了将多个 from子句组合起来的功能,它将每个对象的结果合并成单个可枚举序列。 /// [Fact] public void SelectMany_Test() { var employees = new List() { new Employee(){Id=1,Name="小明",Emails=new List(){ "abc@163.com", "acd@163.com", "ade@163.com" } }, new Employee(){Id=2,Name="大壮",Emails=new List(){ "bbc@163.com", "bcd@163.com", "bde@163.com" } }, new Employee(){Id=3,Name="周羊",Emails=new List(){ "cbc@163.com", "ccd@163.com", "cde@163.com" } }, new Employee(){Id=4,Name="承承",Emails=new List(){ "dbc@163.com", "dcd@163.com", "dde@163.com" } }, new Employee(){Id=5,Name="东升",Emails=new List(){ "ebc@163.com", "ecd@163.com", "ede@163.com" }}, }; var maps = employees.SelectMany(q => q.Emails).ToList(); Assert.IsType>(maps); Assert.Equal(15, maps.Count); } /// /// 将序列的每个元素投影到 IEnumerable,并将结果序列合并为一个序列。每个源元素的索引用于该元素的投影表。 /// /// /// 添加一个对源枚举的索引而已。索引从0开始,最大为TSource.Count-1 /// [Fact] public void SelectMany_Index_Test() { var employees = new List() { new Employee(){Id=1,Name="小明",Emails=new List(){ "abc@163.com", "acd@163.com", "ade@163.com" } }, new Employee(){Id=2,Name="大壮",Emails=new List(){ "bbc@163.com", "bcd@163.com", "bde@163.com" } }, new Employee(){Id=3,Name="周羊",Emails=new List(){ "cbc@163.com", "ccd@163.com", "cde@163.com" } }, new Employee(){Id=4,Name="承承",Emails=new List(){ "dbc@163.com", "dcd@163.com", "dde@163.com" } }, new Employee(){Id=5,Name="东升",Emails=new List(){ "ebc@163.com", "ecd@163.com", "ede@163.com" }}, }; var maps = employees.SelectMany((q, idx) => { q.Emails.Add(idx.ToString()); return q.Emails; }).ToList(); Assert.IsType>(maps); Assert.Equal(20, maps.Count); } /// /// 将序列的每个元素投影到 IEnumerable,并将结果序列合并为一个序列,并对其中每个元素调用结果选择器函数。 /// /// /// 自定义结果项,类似Cross JOIN /// [Fact] public void SelectMany_TCollection_Test() { var employees = new List() { new Employee(){ Id=1,Name="小明",Emails=new List(){ "a1@163.com", "a2@163.com", "a3@163.com" } }, new Employee(){ Id=2,Name="大壮",Emails=new List(){ "b1@163.com", "b2@163.com", "b3@163.com" } }, new Employee(){ Id=3,Name="周羊",Emails=new List(){ "c1@163.com", "c2@163.com", "c3@163.com" } }, new Employee(){ Id=4,Name="承承",Emails=new List(){ "d1@163.com", "d2@163.com", "d3@163.com" } }, new Employee(){ Id=5,Name="东升",Emails=new List(){ "e1@163.com", "e2@163.com", "e3@163.com" } }, }; var maps = employees.SelectMany((employee) => employee.Emails, (person, email) => new { Name = person.Name, Email = email }).ToList(); Assert.Equal(15, maps.Count); } /// /// 将序列的每个元素投影到 IEnumerable,并将结果序列合并为一个序列,并对其中每个元素调用结果选择器函数。 /// 每个源元素的索引用于该元素的中间投影表。 /// /// /// 自定义结果项,类似Cross JOIN /// [Fact] public void SelectMany_TCollection_Index_Test() { var employees = new List() { new Employee(){ Id=1,Name="小明",Emails=new List(){ "a1@163.com", "a2@163.com", "a3@163.com" } }, new Employee(){ Id=2,Name="大壮",Emails=new List(){ "b1@163.com", "b2@163.com", "b3@163.com" } }, new Employee(){ Id=3,Name="周羊",Emails=new List(){ "c1@163.com", "c2@163.com", "c3@163.com" } }, new Employee(){ Id=4,Name="承承",Emails=new List(){ "d1@163.com", "d2@163.com", "d3@163.com" } }, new Employee(){ Id=5,Name="东升",Emails=new List(){ "e1@163.com", "e2@163.com", "e3@163.com" } }, }; var maps = employees.SelectMany ( (employee, idx) => { return new List() { new Employee() { Id = employee.Id, Name = employee.Name + "_" + idx, Emails = employee.Emails } }; }, (person, email) => new { Name = email.Name, Email = email.Emails } ) .ToList(); Assert.Equal(5, maps.Count); } #endregion } }