Difference Between Select and SelectMany
我一直在寻找
有人能提供linq-to-sql示例吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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上的实时演示
select many类似于SQL中的交叉联接操作,它采用交叉积。例如,如果我们
1 2 | Set A={a,b,c} Set B={x,y} |
select many可用于获取以下集合
1 | { (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) } |
请注意,这里我们采用集合A和集合B的元素可以进行的所有可能的组合。
下面是一个您可以尝试的LINQ示例
1 2 3 4 |
混合料的平面结构如下:
1 | {(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)} |
1 2 3 4 5 6 7 | 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 5 6 7 8 9 10 |
前一个例子来自丹的博客。我强烈建议你看一下。
我理解selectmany像一个连接快捷方式一样工作。
所以你可以:
1 2 3 | var orders = customers .Where(c => c.CustomerName =="Acme") .SelectMany(c => c.Orders); |
select是从源元素到结果元素的简单一对一的投影。选择-当查询表达式中有多个FROM子句时使用many:原始序列中的每个元素用于生成新序列。
可能不需要某些selectmany。下面的两个查询给出了相同的结果。
1 2 3 | Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders) Orders.Where(o=>o.Customer.Name=="Tom") |
对于一对多的关系,
1 2 3 4 | from o in Orders join c in Customers on o.CustomerID equals c.ID where c.Name =="Tom" select o |
在不获取太多技术数据库的情况下,多个组织、多个用户:
1 2 3 4 5 6 7 8 9 10 | 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列表。
第一个"项目"从组织到用户,第二个直接查询用户表。
只是为了一个可以帮助一些功能性程序员的替代视图:
Select 为map 。SelectMany 是bind (或flatMap 是你的scala/kotlin人)
更清楚的是,当查询返回字符串(字符数组)时:
例如,如果"水果"列表中包含"苹果"
"select"返回字符串:
1 2 3 | Fruits.Select(s=>s) [0]:"apple" |
"selectmany"使字符串变平:
1 2 3 4 5 6 7 | Fruits.SelectMany(s=>s) [0]: 97 'a' [1]: 112 'p' [2]: 112 'p' [3]: 108 'l' [4]: 101 'e' |
再举一个例子,如何使用selectmany+select来累积子数组对象数据。
假设我们有带电话的用户:
1 2 3 4 5 6 7 8 | class Phone { public string BasePart ="555-xxx-xxx"; } class User { public string Name ="Xxxxx"; public List<Phone> Phones; } |
现在,我们需要选择所有用户的所有手机基础部件:
1 2 | var usersArray = new List<User>(); // array of arrays List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList(); |
我认为这是理解的最好方式。
1 2 3 4 5 6 7 8 9 | 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(); |
乘法表示例。