Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different ways of using SelectMany()

Tags:

c#

linq

I'd like to know how to use SelectMany(). It seems to take so many arguments and from my own research I noticed that SelectMany() might be the 'father' of all other select operations.

like image 874
Ali Tarhini Avatar asked Nov 26 '10 09:11

Ali Tarhini


People also ask

What is select () and SelectMany () in Linq?

Select and SelectMany are projection operators. A select operator is used to select value from a collection and SelectMany operator is used to selecting values from a collection of collection i.e. nested collection.

Can SelectMany return null?

@flem They can never be null because that's how Where and SelectMany work. If the input is null they throw an exception, and if it's not null the result will either be a sequence of items, or an empty sequence.

What is the difference between FirstOrDefault and SingleOrDefault?

SingleOrDefault() – Same as Single(), but it can handle the null value. First() - There is at least one result, an exception is thrown if no result is returned. FirstOrDefault() - Same as First(), but not thrown any exception or return null when there is no result.

What is the difference between returning IQueryable T vs IEnumerable T?

The major difference between IQueryable and IEnumerable is that IQueryable executes query with filters whereas IEnumerable executes the query first and then it filters the data based on conditions.


2 Answers

Select many allows you to select a property from your query source that is an IEnumerable<T> collection, but instead of returning a collection of collections (IEnumerable<IEnumerable<T>>) it will flatten the collections into a single collection.

Here's an example that you can run to demonstrate the differences between Select and SelectMany:

//set up some data for our example
var tuple1 = new { Name = "Tuple1", Values = new int [] { 1, 2, 3 } };
var tuple2 = new { Name = "Tuple2", Values = new int [] { 4, 5, 6 } };
var tuple3 = new { Name = "Tuple3", Values = new int [] { 7, 8, 9 } };

//put the tuples into a collection
var tuples = new [] { tuple1, tuple2, tuple3 };

//"tupleValues" is an IEnumerable<IEnumerable<int>> that contains { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }
var tupleValues = tuples.Select(t => t.Values);

//"tupleSelectManyValues" is an IEnumerable<int> that contains { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
var tupleSelectManyValues = tuples.SelectMany(t => t.Values);

By using SelectMany you make it easier to query values within child collections.

like image 193
Doctor Jones Avatar answered Sep 23 '22 10:09

Doctor Jones


There are several overloads to SelectMany. One of them allows you to keep track 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 loose any reference to the team a 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:

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

I strongly recommend you take a look at it.

like image 37
roland Avatar answered Sep 22 '22 10:09

roland