Select和SelectMany之间的区别

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

有人可以提供一个LINQ to 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 }); 

在.NET小提琴现场演示

选择很多就像在SQL中的交叉连接操作,其中跨产品。
例如,如果我们有

 Set A={a,b,c} Set B={x,y} 

选择许多可用于获得以下设置

 { (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) } 

请注意,这里我们从集合A和集合B的元素中取出所有可能的组合。

这是一个可以尝试的LINQ示例

  List<string> animals = new List<string>() { "cat", "dog", "donkey" }; List<int> number = new List<int>() { 10, 20 }; var mix=number.SelectMany(num => animals, (n, a) => new { n, a }); 

混合将有以下元素在平面结构像

 {(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)} 

在这里输入图像描述

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

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

  1. 罗纳尔多
  2. 梅西
  3. 法布雷加斯
  4. 卡西利亚斯

SelectMany()让你折叠多维序列,否则将需要第二个Select()或循环。

更多细节在这个博客文章 。

SelectMany有几个重载。 其中之一允许您在遍历层次结构时保留父级和子级之间的任何关系的跟踪。

例如 :假设你有以下结构: League -> Teams -> Player

你可以轻松地返回一个单位的球员集合。 但是,您可能会失去对玩家所属团队的任何提及。

幸运的是,有这样的目的超载:

 var teamsAndTheirLeagues = from helper in leagues.SelectMany ( l => l.Teams , ( league, team ) => new { league, team } ) where helper.team.Players.Count > 2 && helper.league.Teams.Count < 10 select new { LeagueID = helper.league.ID , Team = helper.team }; 

前面的例子取自Dan的IK博客:

http://blogs.interknowlogy.com/2008/10/10/use-linqs-selectmany-method-to-flatten-collections/

我强烈建议你看看它。

我明白SelectMany像加入快捷方式一样工作。

所以你可以:

 var orders = customers .Where(c => c.CustomerName == "Acme") .SelectMany(c => c.Orders); 

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

一些SelectMany可能不是必需的。 以下2个查询给出相同的结果。

 Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders) Orders.Where(o=>o.Customer.Name=="Tom") 

对于一对多的关系,

  1. 如果从“1”开始,SelectMany是必要的,它使许多平坦。
  2. 如果从“Many”开始,则不需要SelectMany。 ( 仍然可以从“1”过滤 ,也比下面的标准连接查询更简单)

 from o in Orders join c in Customers on o.CustomerID equals c.ID where c.Name == "Tom" select o 

没有太多的技术 – 数据库与许多组织,每个有许多用户: –

 var orgId = "123456789"; var userList1 = db.Organizations .Where(a => a.OrganizationId == orgId) .SelectMany(a => a.Users) .ToList(); var userList2 = db.Users .Where(a => a.OrganizationId == orgId) .ToList(); 

都返回所选组织的相同 ApplicationUser列表。

从组织到用户的第一个“项目”,第二个直接查询用户表。

只是为了替代视图,可以帮助一些功能程序员:

  • Selectmap
  • SelectManybind (或您的Scala / Kotlin人的flatMap

当查询返回一个字符串时更加清楚:

例如,如果列表“文件”包含文件名'afile.txt'

'选择'返回字符串:

 Files.Select(f=>f.Filename) [0]: "afile.txt" 

'SelectMany'将字符串弄平:

 Files.SelectMany(f=>f.Filename) [0]: 97 'a' [1]: 102 'f' [2]: 105 'i' [3]: 108 'l' [4]: 101 'e' [5]: 46 '.' [6]: 116 't' [7]: 120 'x' [8]: 116 't' 

这是了解我的想法的最好方法。

  var query = Enumerable .Range(1, 10) .SelectMany(ints => Enumerable.Range(1, 10), (a, b) => $"{a} * {b} = {a * b}") .ToArray(); Console.WriteLine(string.Join(Environment.NewLine, query)); Console.Read(); 

乘法表示例。