C# LINQ SelectMany
last modified July 5, 2023
In this article we show how to flatten sequences into a single sequence with
LINQ's SelectMany method.
Language-Integrated Query (LINQ) is a domain-specific language for querying data from various data sources, including arrays, lists, XML files, or databases.
The SelectMany method flattens a number of sequences into a single
sequence.
C# LINQ SelectMany array of arrays
The first example is a simple program which uses LINQ SelectMany
method.
int[][] vals = {
new[] {1, 2, 3},
new[] {4},
new[] {5, 6, 6, 2, 7, 8},
};
var res = vals.SelectMany(a => a).OrderBy(e => e);
Console.WriteLine(string.Join(", ", res));
In the program, we have an array of arrays. With the SelectMany
method, we flatten the two-dimensional array into an one-dimensional array
values. The values are also ordered.
$ dotnet run 1, 2, 2, 3, 4, 5, 6, 6, 7, 8
C# LINQ SelectMany Distinct
The Distinct method is used to get unique values.
var vals = new List<List<int>> {
new List<int> {1, 2, 3, 3},
new List<int> {4},
new List<int> {5, 6, 6, 7, 7}
};
var res = vals.SelectMany(list => list)
.Distinct()
.OrderByDescending(e => e);
Console.WriteLine(string.Join(", ", res));
In the program, we flatten all integers from a list of lists into a single sequence. We pick up only unique values and order them in descending order.
$ dotnet run 7, 6, 5, 4, 3, 2, 1
C# LINQ SelectMany string list
In the next example, we apply the SelectMany method on a list of
strings.
var ru_words = new List<string> { "осторожность", "собака", "облако", "чашка" };
var res = ru_words.SelectMany(e => e);
Console.WriteLine(string.Join(",", res));
We define a list of Russian words. The SelectMany cuts the words
into letters and forms a single sequence from them.
$ dotnet run о,с,т,о,р,о,ж,н,о,с,т,ь,с,о,б,а,к,а,о,б,л,а,к,о,ч,а,ш,к,а
C# LINQ SelectMany on record field
The next example applies the SelectMany method on a record field.
var users = new List<User>
{
new ("John", "Doe", new List<string> { "red", "blue" }),
new ("Roger", "Roe", new List<string> { "black", "yellow" }),
new ("Jerry", "Dane", new List<string> { "blue", "orange", "white" }),
new ("Thomas", "Green", new List<string> { "brown" }),
};
List<string> res = users.SelectMany(e => e.colours).ToList();
Console.WriteLine(string.Join(",", res));
record User(string fname, string lname, List<string> colours);
We have a list of users, who have their favourite colours specified. The colours are defined as a list of strings inside a record type.
List<string> res = users.SelectMany(e => e.colours).ToList();
The flattening operation is applied on the colours fields of the
records.
$ dotnet run red,blue,black,yellow,blue,orange,white,brown
C# LINQ Select
We can perform the same operations with Select; the
SelectMany is more convenient.
var users = new List<User>
{
new ("John", "Doe", new List<string> { "red", "blue" }),
new ("Roger", "Roe", new List<string> { "black", "yellow" }),
new ("Jerry", "Dane", new List<string> { "blue", "orange", "white" }),
new ("Thomas", "Green", new List<string> { "brown" }),
};
IEnumerable<List<string>> res = users.Select(e => e.colours).ToList();
List<string> colours = new List<string>();
foreach(var cols in res)
{
foreach (var col in cols)
{
colours.Add(col);
}
}
Console.WriteLine(string.Join(",", colours));
colours.Clear();
foreach (var data in res)
{
colours.AddRange(data);
}
Console.WriteLine(string.Join(",", colours));
record User(string fname, string lname, List<string> colours);
In the example we flatten all favourite colours into a list of strings.
foreach(var cols in res)
{
foreach (var col in cols)
{
colours.Add(col);
}
}
In the first case, we use two foreach loops.
foreach (var data in res)
{
colours.AddRange(data);
}
In the second case, we use a foreach loop and the AddRange method.
$ dotnet run red,blue,black,yellow,blue,orange,white,brown red,blue,black,yellow,blue,orange,white,brown
Source
In this article we have presented the LINQ SelectMany method.
Author
List all C# tutorials.