Difference Between Select and SelectMany

后端 未结 17 1108
长情又很酷
长情又很酷 2020-11-22 05:21

I\'ve been searching the difference between Select and SelectMany but I haven\'t been able to find a suitable answer. I need to learn the differenc

相关标签:
17条回答
  • 2020-11-22 05:22

    SelectMany flattens queries that return lists of lists. For example

    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 on .NET Fiddle

    0 讨论(0)
  • It's more clear when the query return a string (an array of char):

    For example if the list 'Fruits' contains 'apple'

    'Select' returns the string:

    Fruits.Select(s=>s) 
    
    [0]: "apple"
    

    'SelectMany' flattens the string:

    Fruits.SelectMany(s=>s)
    
    [0]: 97  'a'
    [1]: 112 'p'
    [2]: 112 'p'
    [3]: 108 'l'
    [4]: 101 'e'
    
    0 讨论(0)
  • 2020-11-22 05:27

    There are several overloads to SelectMany. One of them allows you to keep trace of any relationship between parent and children while traversing the hierarchy.

    Example: suppose you have the following structure: League -> Teams -> Player.

    You can easily return a flat collection of players. However you may lose any reference to the team the player is part of.

    Fortunately there is an overload for such purpose:

    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 
                                       };
    

    The previous example is taken from Dan's IK blog. I strongly recommend you take a look at it.

    0 讨论(0)
  • 2020-11-22 05:27

    The SelectMany method knocks down an IEnumerable<IEnumerable<T>> into an IEnumerable<T>, like communism, every element is behaved in the same manner(a stupid guy has same rights of a genious one).

    var words = new [] { "a,b,c", "d,e", "f" };
    var splitAndCombine = words.SelectMany(x => x.Split(','));
    // returns { "a", "b", "c", "d", "e", "f" }
    
    0 讨论(0)
  • 2020-11-22 05:29

    Select many is like cross join operation in SQL where it takes the cross product.
    For example if we have

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

    Select many can be used to get the following set

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

    Note that here we take the all the possible combinations that can be made from the elements of set A and set B.

    Here is a LINQ example you can try

    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 });
    

    the mix will have following elements in flat structure like

    {(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}
    
    0 讨论(0)
  • 2020-11-22 05:30

    The SelectMany() method is used to flatten a sequence in which each of the elements of the sequence is a separate.

    I have class user same like this

    class User
        {
            public string UserName { get; set; }
            public List<string> Roles { get; set; }
        }
    

    main:

    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 }
    
    

    You can use operations on any item of sequence

    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 }
    
     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 }
    
    0 讨论(0)
提交回复
热议问题