Select和SelectMany之间的区别

Tar*_*rik 993 c# linq linq-to-sql

我一直在寻找和之间的区别Select,SelectMany但我找不到合适的答案.我需要了解使用LINQ To SQL时的不同之处,但我发现的只是标准数组示例.

有人可以提供LINQ To SQL示例吗?

Mik*_*Two 1532

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 });
Run Code Online (Sandbox Code Playgroud)

.NET小提琴上的现场演示


Sri*_*ake 177

选择很多就像SQL中的交叉连接操作一样,它需要交叉产品.
例如,如果我们有

Set A={a,b,c}
Set B={x,y}
Run Code Online (Sandbox Code Playgroud)

选择多个可用于获取以下设置

{ (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) }
Run Code Online (Sandbox Code Playgroud)

请注意,这里我们采用可以从集合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 });
Run Code Online (Sandbox Code Playgroud)

混合物将具有扁平结构的以下元素

{(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}
Run Code Online (Sandbox Code Playgroud)

  • SelectMany不必像这样使用.它也可以选择一个功能. (4认同)
  • 我知道这已经过时了,但我想感谢你,这让我节省了很多!:)引用这些代码也很有用:http://stackoverflow.com/questions/3479980/select-all-unique-combinations-of-a-single-list-with-no-repeats-using -linq干杯! (3认同)
  • 我不知道这是否是SelectMany * *的正确方式。相反,这是可以使用“ SelectMany”的方式,但实际上不是使用它的正常方式。 (2认同)
  • 这是我能理解的最简单的答案。 (2认同)

Ale*_*roR 118

在此输入图像描述

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

foreach(var player in players)
{
    Console.WriteLine(player.LastName);
}
Run Code Online (Sandbox Code Playgroud)
  1. 德吉亚
  2. 阿尔巴
  3. 哥斯达黎加
  4. 别墅
  5. 布斯克茨

...

  • 很好的示例数据 (9认同)
  • 您能否为 select 添加一个示例以完成此答案:) (4认同)

Mic*_*tta 73

SelectMany()允许您以一种原本需要第二个Select()或循环的方式折叠多维序列.

博客文章的更多细节.


rol*_*and 34

有几个重载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 
                                   };
Run Code Online (Sandbox Code Playgroud)

前面的例子来自Dan的IK博客.我强烈建议你看一下.


Nat*_*oop 19

我理解SelectMany像连接快捷方式一样工作.

所以你可以:

var orders = customers
             .Where(c => c.CustomerName == "Acme")
             .SelectMany(c => c.Orders);
Run Code Online (Sandbox Code Playgroud)

  • 提供的示例有效,但 **SelectMany** 不像连接那样工作。联接允许“使用”原始表的任何字段以及联接表的任何字段。但是在这里您必须指定附加到原始表的列表对象。例如,`.SelectMany(c =&gt; new {c.CompanyName, c.Orders.ShippedDate});` 将不起作用。SelectMany 相当扁平化列表列表 - 您可以选择任何(但一次只能选择一个)包含的列表作为结果。比较:[Linq 中的内连接](/sf/answers/2613271/)。 (2认同)

Rez*_*abi 14

所述的SelectMany()方法用于变平的序列,其中每个序列的元素的是一个单独的。

我有类user相同这样的

class User
    {
        public string UserName { get; set; }
        public List<string> Roles { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

主要的:

var users = new List<User>
            {
                new User { UserName = "Reza" , Roles = new List<string>{"Superadmin" } },
                new User { UserName = "Amin" , Roles = new List<string>{"Guest","Reseption" } },
                new User { UserName = "Nima" , Roles = new List<string>{"Nurse","Guest" } },
            };

var query = users.SelectMany(user => user.Roles, (user, role) => new { user.UserName, role });

foreach (var obj in query)
{
    Console.WriteLine(obj);
}
//output

//{ UserName = Reza, role = Superadmin }
//{ UserName = Amin, role = Guest }
//{ UserName = Amin, role = Reseption }
//{ UserName = Nima, role = Nurse }
//{ UserName = Nima, role = Guest }

Run Code Online (Sandbox Code Playgroud)

您可以对序列的任何项目使用操作

int[][] numbers = {
                new[] {1, 2, 3},
                new[] {4},
                new[] {5, 6 , 6 , 2 , 7, 8},
                new[] {12, 14}
            };

IEnumerable<int> result = numbers
                .SelectMany(array => array.Distinct())
                .OrderBy(x => x);

//output

//{ 1, 2 , 2 , 3, 4, 5, 6, 7, 8, 12, 14 }
Run Code Online (Sandbox Code Playgroud)
 List<List<int>> numbers = new List<List<int>> {
                new List<int> {1, 2, 3},
                new List<int> {12},
                new List<int> {5, 6, 5, 7},
                new List<int> {10, 10, 10, 12}
            };

 IEnumerable<int> result = numbers
                .SelectMany(list => list)
                .Distinct()
                .OrderBy(x=>x);

//output

// { 1, 2, 3, 5, 6, 7, 10, 12 }
Run Code Online (Sandbox Code Playgroud)


Ale*_*ndr 13

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


nzr*_*tmn 9

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
  */
Run Code Online (Sandbox Code Playgroud)

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

因此 SelectMany 的结果是一个类似的列表

{邋遢、萨姆、沃克、糖、划痕、柴油}

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


Rm5*_*558 7

某些SelectMany可能没有必要.低于2的查询给出相同的结果.

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

Orders.Where(o=>o.Customer.Name=="Tom")
Run Code Online (Sandbox Code Playgroud)

对于1对多的关系,

  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
Run Code Online (Sandbox Code Playgroud)


Mat*_*ein 5

只是为了提供可能对一些函数式程序员有所帮助的替代视图:

  • Selectmap
  • SelectManybind(或者flatMap对于你的 Scala/Kotlin 人员)