08 LINQ中的SelectMany(Select Many Operator in LINQ)

SelectMany函数可以将返回的List展开为List。理解这句话的最好方式是通过一个例子:

public class Person
{
    public string FirstName;
    public string LastName;
    public string Gender;
    public int AnualSalary;
    public List<string> PhoneNumber;

    public static List<Person> GetAllPerson()
    {
        List<Person> personInList = new List<Person>()
        {
            new Person()
            {
                 FirstName = "Jonh",
                 LastName = "Liu",
                 Gender = "Male",
                 AnualSalary = 70000,
                 PhoneNumber = new List<string>()
                 {
                     "0101235566",
                     "12056878445"
                 }
            },
            new Person()
            {
                 FirstName = "Sara",
                 LastName = "Guo",
                 Gender = "Famale",
                 AnualSalary = 100000,
                 PhoneNumber = new List<string>()
                 {
                     "13356985469",
                     "15536215459"
                 }
            },
            new Person()
            {
                 FirstName="Marttin",
                 LastName = "Zeng",
                 Gender = "Male",
                 AnualSalary = 80000,
                 PhoneNumber = new List<string>()
                 {
                     "15862354569",
                     "13756542698",
                     "15936545269"
                 }
            },
            new Person()
            {
                 FirstName="Sccot",
                 LastName= "Jiang",
                 Gender = "Male",
                 AnualSalary = 90000,
                 PhoneNumber = new List<string>()
                 {
                     "02388695645"
                 }
            }
        };

        return personInList;
    }
}

上面的代码中,Person类中有一个List<string>类型的名为PhoneNumber的属性。如果我们要获取性别为“男”的List<Person>的所有PhoneNumer我们可以用Select语句:

 List<Person> personInList = Person.GetAllPerson();
 IEnumerable<List<string>> marttinsPhoneNumberList = personInList.Where(p => p.Gender == "Male").Select(p => p.PhoneNumber);
 foreach (List<string> eachPhoneNumberList in marttinsPhoneNumberList)
 {
     foreach (string eachPhoneNumber in eachPhoneNumberList)
     {
         Console.WriteLine(eachPhoneNumber);
     }
     Console.WriteLine(new string(‘-‘, 20));
 }

可以看到,我们用Select函数筛选的结果是IEnumerable<List<string>>类型。这很好理解,因为PhoneNumber在Person类中本来就是一个List<string>类型。但如果我们用SelectMany函数会发生什么呢?请看下面的代码:

List<Person> personInList = Person.GetAllPerson();
IEnumerable<string> allPhoneNumberInList = personInList.Where(p => p.Gender == "Male").SelectMany(p => p.PhoneNumber);
foreach (string eachPhoneNumber in allPhoneNumberInList)
{
    Console.WriteLine(eachPhoneNumber);
}

事实上,我们必须用IEnumerable<string>来接收SelectMany的返回值!因为SelectMany会将返回的类型为List<string>的PhoneNumber进一步展开为IEnumerable<string>类型。这也就解释了文章开头的“SelectMany函数可以将返回的List展开为List”的意思。再举一个例子,如果我们运行下面的代码:

List<Person> personInList = Person.GetAllPerson();
IEnumerable<char> allCharOfLastName = personInList.Where(p => p.FirstName == "Sccot").SelectMany(p => p.LastName);
foreach (char eachChar in allCharOfLastName)
{
    Console.WriteLine(eachChar);
}

上面的代码首先选出了FirstName为"Sccot"的person,然后用SelectMany返回其LastName。注意LastName的类型为string,SelectMany返回的结果是把string展开为一个char类型的List了。

SelectMany还有另外的重载。例如,如果我们想同时显示FullName和对应的PhoneNumber的话,可以使用下面的代码达到目的:

List<Person> personInList = Person.GetAllPerson();
var result = personInList.Where(p => p.Gender == "Male").SelectMany(p => p.PhoneNumber, (person, phoneNumber) => new { FullName = person.FirstName + " " + person.LastName, PhoneNumber = phoneNumber });
foreach (var item in result)
{
    Console.WriteLine(string.Format("FullName:{0}\r\nPhoneNumber:{1}", item.FullName, item.PhoneNumber));
}

参考:http://stackoverflow.com/questions/958949/difference-between-select-and-selectmany

时间: 2024-11-02 13:35:32

08 LINQ中的SelectMany(Select Many Operator in LINQ)的相关文章

04 LINQ中的聚合函数(Aggregate function in LINQ)

试想一下,我们有一个List<int>数组,现在我们想对List中的所有值求和.在没学习LINQ之前我们会轻松的写出下面的代码: static void Main(string[] args) { List<int> array = new List<int>() { 1, 3, 3, 2, 7, 3, 2, 8, 5, 4, 6 }; int sum = 0; foreach (int item in array) { sum += item; } Console.W

Entity Framework 6 Recipes 2nd Edition(11-9)译 -&gt; 在LINQ中使用规范函数

11-9. 在LINQ中使用规范函数 问题 想在一个LINQ查询中使用规范函数 解决方案 假设我们已经有一个影片租赁(MovieRental )实体,它保存某个影片什么时候租出及还回来,以及滞纳金等,如Figure 11-9. 所示: Figure 11-9. The MovieRental entity that has the dates for a rental period along with any late fees 我们想取得所有租期超过10天的影片 如何创建和使用查询,如Lis

Linq 中 Join 的用法

Linq中连接主要有组连接.内连接.左外连接.交叉连接四种.各个用法如下. 注:本文内容主要来自<Linq实战>,本例中用到的对象请见文章底部. 1. 组连接 组连接是与分组查询是一样的.即根据分组得到结果. 如下例,根据publisther分组得到结果. 使用组连接的查询语句如下: //使用组连接            var GroupQuery = from publisher in SampleData.Publishers                             jo

LINQ:开始使用 LINQ(五)- LINQ 中的查询语法和方法语法

开始使用 LINQ(五)- LINQ 中的查询语法和方法语法 在表示语言集成查询 (LINQ) 使用 LINQ 性查询语法,文档中的多数查询编写.但是,编译代码时,必须将查询语法转换为方法,这就需要 .NET 公共语言运行时 (CLR).这些方法调用标准查询运算符的名称类似 Where.Select.GroupBy.Join.Max和 Average.可以调用这些方法直接使用方法语法而不是查询语法. 查询语法和方法语法语义相同,但是,许多人员发现查询语法更简单.更易于阅读.某些查询必须表示为方法

数据库和linq中的 join(连接)操作

sql中的连接 sql中的表连接有inner join,left join(left outer join),right join(right outer join),full join(full outer join),cross join 在此基础上我们能扩展出 left excluding join,right excluding join,full outer excluding join 注:left join是left outer join 的简写,即左连接和左外连接是一样的 首先定

LINQ中的连接(join)用法示例

Linq中连接主要有组连接.内连接.左外连接.交叉连接四种.各个用法如下. 1. 组连接 组连接是与分组查询是一样的.即根据分组得到结果. 如下例,根据publisther分组得到结果. 使用组连接的查询语句如下: //使用组连接 var GroupQuery = from publisher in SampleData.Publishers join book in SampleData.Books on publisher equals book.Publisher into publish

Linq中的连接(join)

Linq中连接主要有组连接.内连接.左外连接.交叉连接四种.各个用法如下. 注:本文内容主要来自<Linq实战>,本例中用到的对象请见文章底部. 1. 组连接 组连接是与分组查询是一样的.即根据分组得到结果. 如下例,根据publisther分组得到结果. 使用组连接的查询语句如下: //使用组连接            var GroupQuery = from publisher in SampleData.Publishers                             jo

C++中的new/delete与operator new/operator delete

new operator/delete operator就是new和delete操作符,而operator new/operator delete是函数. new operator(1)调用operator new分配足够的空间,并调用相关对象的构造函数(2)不可以被重载 operator new(1)只分配所要求的空间,不调用相关对象的构造函数.当无法满足所要求分配的空间时,则        ->如果有new_handler,则调用new_handler,否则        ->如果没要求不

LINQ中的一些查询语句格式

LINQ的基本格式如下所示:var <变量> = from <项目> in <数据源> where <表达式> orderby <表达式> LINQ 基本子句from查询子句——基础后面跟随着项目名称和数据源示例代码如下:var str = from lq in str select lq; 其中select语句指定了返回到集合变量中的元素是来自哪个数据源的 from查询子句——嵌套查询可以在from子句中嵌套另一个from子句即可,示例代码如下