我一直在搜索Select和SelectMany之间的区别,但我还没有找到合适的答案。我需要学习使用LINQ to SQL时的差异,但我所找到的都是标准数组示例。

有人能提供一个LINQ到SQL的例子吗?


当前回答

SelectMany扁平查询,返回列表的列表。例如

public class PhoneNumber
{
    public string Number { get; set; }
}

public class Person
{
    public IEnumerable<PhoneNumber> PhoneNumbers { get; set; }
    public string Name { get; set; }
}

IEnumerable<Person> people = new List<Person>();

// Select gets a list of lists of phone numbers
IEnumerable<IEnumerable<PhoneNumber>> phoneLists = people.Select(p => p.PhoneNumbers);

// SelectMany flattens it to just a list of phone numbers.
IEnumerable<PhoneNumber> phoneNumbers = people.SelectMany(p => p.PhoneNumbers);

// And to include data from the parent in the result: 
// pass an expression to the second parameter (resultSelector) in the overload:
var directory = people
   .SelectMany(p => p.PhoneNumbers,
               (parent, child) => new { parent.Name, child.Number });

Live Demo。net Fiddle

其他回答

只是为了另一种观点,可能会帮助一些函数式程序员:

选择是映射 SelectMany是绑定的(或flatMap的Scala/Kotlin人)

假设你有一组国家

var countries = new[] { "France", "Italy" };

如果你对国家执行Select,你将得到数组中的每个元素IEnumerable<T>

IEnumerable<string> selectQuery = countries.Select(country => country);

在上面的代码中,国家表示指向数组中每个国家的字符串。现在迭代selectQuery以获得国家:

foreach(var country in selectQuery)
    Console.WriteLine(country);

// output
//
// France
// Italy

如果你想打印每个国家的字符,你必须使用嵌套foreach

foreach (var country in selectQuery)
{
    foreach (var charOfCountry in country)
    {
        Console.Write(charOfCountry + ", ");
    }
}

// output

// F, r, a, n, c, e, I, t, a, l, y,

好的。现在尝试对国家执行SelectMany。这一次SelectMany获取每个国家作为字符串(和以前一样),因为字符串类型是一个字符的集合,SelectMany尝试将每个国家分为它的组成部分(字符),然后返回一个字符的集合IEnumerable<T>

IEnumerable<char> selectManyQuery = countries.SelectMany(country => country);

在上面的代码中,country表示一个字符串,该字符串引用数组中的每个国家,但返回值是每个国家的字符

实际上SelectMany喜欢在集合中获取两层,并将第二层平铺为IEnumerable<T>

现在遍历selectManyQuery以获得每个国家的字符:

foreach(var charOfCountry in selectManyQuery)
    Console.Write(charOfCountry + ", ");

// output

// F, r, a, n, c, e, I, t, a, l, y,

SelectMany()的正式描述是:

将序列的每个元素投射到IEnumerable上并展开 产生的序列变成一个序列。

SelectMany()将结果序列平铺成一个序列,并对其中的每个元素调用结果选择器函数。

class PetOwner
{
    public string Name { get; set; }
    public List<String> Pets { get; set; }
}

public static void SelectManyEx()
{
     PetOwner[] petOwners =
         { new PetOwner { Name="Higa, Sidney",
              Pets = new List<string>{ "Scruffy", "Sam" } },
           new PetOwner { Name="Ashkenazi, Ronen",
              Pets = new List<string>{ "Walker", "Sugar" } },
           new PetOwner { Name="Price, Vernette",
              Pets = new List<string>{ "Scratches", "Diesel" } } };

// Query using SelectMany().
IEnumerable<string> query1 = petOwners.SelectMany(petOwner => petOwner.Pets);

Console.WriteLine("Using SelectMany():");

// Only one foreach loop is required to iterate
// through the results since it is a
// one-dimensional collection.
foreach (string pet in query1)
{
    Console.WriteLine(pet);
}

// This code shows how to use Select()
// instead of SelectMany().
IEnumerable<List<String>> query2 =
    petOwners.Select(petOwner => petOwner.Pets);

Console.WriteLine("\nUsing Select():");

// Notice that two foreach loops are required to
// iterate through the results
// because the query returns a collection of arrays.
foreach (List<String> petList in query2)
{
    foreach (string pet in petList)
    {
        Console.WriteLine(pet);
    }
    Console.WriteLine();
}
}

/*
   This code produces the following output:

    Using SelectMany():
    Scruffy
    Sam
    Walker
    Sugar
    Scratches
    Diesel

   Using Select():
   Scruffy
   Sam

   Walker
   Sugar

   Scratches
   Diesel
  */

主要的区别是每个方法的结果,而SelectMany()返回一个扁平的结果;Select()返回一个列表的列表,而不是一个扁平的结果集。

因此,SelectMany的结果是一个列表

{斯库菲,山姆,沃克,甜甜,划痕,迪塞尔}

你可以迭代每一项。但是对于select的结果,您需要一个额外的foreach循环来遍历结果,因为查询返回一个数组集合。

var players = db.SoccerTeams.Where(c => c.Country == "Spain")
                            .SelectMany(c => c.players);

foreach(var player in players)
{
    Console.WriteLine(player.LastName);
}

De Gea 阿尔芭 科斯塔 别墅 Busquets

...

Select是一个简单的从源元素到结果元素的一对一投影。选择- - - 当查询表达式中有多个from子句时使用Many:原始序列中的每个元素都用于生成一个新序列。