Projection in LINQ C# with the SelectMany operator

The SelectMany operator creates a one-to-many output projection sequence over an input sequence. SelectMany will return 0 or more output elements for every input element. Let’s see an example.

Data source:

string[] bands = { "ACDC", "Queen", "Aerosmith", "Iron Maiden", "Megadeth", "Metallica", "Cream", "Oasis", "Abba", "Blur", "Chic", "Eurythmics", "Genesis", "INXS", "Midnight Oil", "Kent", "Madness", "Manic Street Preachers"
, "Noir Desir", "The Offspring", "Pink Floyd", "Rammstein", "Red Hot Chili Peppers", "Tears for Fears"
, "Deep Purple", "KISS"};

Consider the following code:

IEnumerable<char> characters = bands.SelectMany(b => b.ToArray());
foreach (char item in characters)
{
	Console.WriteLine(item);
}

We provide a string input to SelectMany and apply the ToArray extension to it which will be an array of chars. So we have a single input – a string – and a collection of many elements as output – the sequence of characters from each band name.

Here’s a small part of the output:

SelectMany operator simple example

This is an interesting but probably not too useful application of SelectMany. We can do more interesting projections with it. Consider the following classes:

public class Singer
{
	public int Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
}
public class Concert
{
	public int SingerId { get; set; }
	public int ConcertCount { get; set; }
	public int Year { get; set; }
}

We have the following data in the data collection:

public static IEnumerable<Singer> GetSingers()
{
	return new List<Singer>() 
	{
		new Singer(){Id = 1, FirstName = "Freddie", LastName = "Mercury"} 
		, new Singer(){Id = 2, FirstName = "Elvis", LastName = "Presley"}
		, new Singer(){Id = 3, FirstName = "Chuck", LastName = "Berry"}
		, new Singer(){Id = 4, FirstName = "Ray", LastName = "Charles"}
		, new Singer(){Id = 5, FirstName = "David", LastName = "Bowie"}
	};
}
public static IEnumerable<Concert> GetConcerts()
{
	return new List<Concert>()
	{
		new Concert(){SingerId = 1, ConcertCount = 53, Year = 1979}
		, new Concert(){SingerId = 1, ConcertCount = 74, Year = 1980}
		, new Concert(){SingerId = 1, ConcertCount = 38, Year = 1981}
		, new Concert(){SingerId = 2, ConcertCount = 43, Year = 1970}
		, new Concert(){SingerId = 2, ConcertCount = 64, Year = 1968}
		, new Concert(){SingerId = 3, ConcertCount = 32, Year = 1960}
		, new Concert(){SingerId = 3, ConcertCount = 51, Year = 1961}
		, new Concert(){SingerId = 3, ConcertCount = 95, Year = 1962}
		, new Concert(){SingerId = 4, ConcertCount = 42, Year = 1950}
		, new Concert(){SingerId = 4, ConcertCount = 12, Year = 1951}
		, new Concert(){SingerId = 5, ConcertCount = 53, Year = 1983}
	};
}

We can create a join with the SelectMany operator to see how many concerts each singer gave per year. Consider the following query:

IEnumerable<Singer> singers = GetSingers();
IEnumerable<Concert> concerts = GetConcerts();

var singerConcerts = singers.SelectMany(s => concerts.Where(c => c.SingerId == s.Id)
	.Select(c => new {Year = c.Year, ConcertCount = c.ConcertCount, Name = string.Concat(s.FirstName, " ", s.LastName) }));

foreach (var item in singerConcerts)
{
	Console.WriteLine(string.Concat(item.Name, ", ", item.Year, ", ", item.ConcertCount));
}

First every Singer object is passed into the lambda expression of SelectMany, which will be ‘s’ parameter. In the lambda expression we retrieve every Concert of each singer using the Where extension. We’re in effect joining the two data collections on the Id/SingerId properties. Finally we construct an anonymous object collection with the Select operator. Here’s the output:

SelectMany operator complex example

You can project the results into “real” objects as opposed to anonymous ones. We have the following object:

public class SingerConcert
{
	public string SingerName { get; set; }
	public int Year { get; set; }
	public int ConcertCount { get; set; }
}

Our query can be modified as follows to build a sequence of SingerConcert objects:

IEnumerable<Singer> singers = DemoCollections.GetSingers();
IEnumerable<Concert> concerts = DemoCollections.GetConcerts();

IEnumerable<SingerConcert> singerConcerts = singers.SelectMany(s => concerts.Where(c => c.SingerId == s.Id)
	.Select(c => new SingerConcert() { Year = c.Year, ConcertCount = c.ConcertCount, SingerName = string.Concat(s.FirstName, " ", s.LastName) }));

foreach (SingerConcert item in singerConcerts)
{
	Console.WriteLine(string.Concat(item.SingerName, ", ", item.Year, ", ", item.ConcertCount));
}

…which provides the same output as the anonymous class example above.

You can view all LINQ-related posts on this blog here.

Projection in LINQ C# with the Select operator

You can use the Select() extension method in LINQ to create an output of type T from an input sequence of type other than T. Let’s see some examples:

Source data:

string[] bands = { "ACDC", "Queen", "Aerosmith", "Iron Maiden", "Megadeth", "Metallica", "Cream", "Oasis", "Abba", "Blur" , "Chic", "Eurythmics", "Genesis", "INXS", "Midnight Oil", "Kent", "Madness", "Manic Street Preachers", "Noir Desir", "The Offspring", "Pink Floyd", "Rammstein", "Red Hot Chili Peppers", "Tears for Fears", "Deep Purple", "KISS"};

Say you want to collect the lengths of each string in the array:

IEnumerable<int> lengths = bands.Select(b => b.Length);
foreach (int l in lengths)
{
	Console.WriteLine(l);
}

Select operator simple output

You can also project to a sequence of anonymous objects…:

var customObjects = bands.Select(b => new { Name = b, Length = b.Length });
foreach (var item in customObjects)
{
	Console.WriteLine("Band name: {0}, length: {1}", item.Name, item.Length);
}

Select operator extended output

…or to different concrete objects:

public class Band
{
	public string Name { get; set; }
	public int NameLength { get; set; }
	public string AllCapitals { get; set; }
}

IEnumerable<Band> bandList = bands.Select(b => new Band() { AllCapitals = b.ToUpper(), Name = b, NameLength = b.Length });
foreach (Band band in bandList)
{
	Console.WriteLine(string.Concat(band.Name, ", ", band.NameLength, ", ", band.AllCapitals));
}

Select operator custom object output

An overload of Select() allows us to read an index value:

public class Band
{
	public string Name { get; set; }
	public int NameLength { get; set; }
	public string AllCapitals { get; set; }
	public int BandIndex { get; set; }
}

IEnumerable<Band> bandList = bands.Select((b, i) => new Band() { AllCapitals = b.ToUpper(), BandIndex = i + 1, Name = b, NameLength = b.Length });
foreach (Band band in bandList)
{
	Console.WriteLine(string.Concat(band.BandIndex, ": ", band.Name, ", ", band.NameLength, ", ", band.AllCapitals));
}

Select operator indexed object output

You can view all LINQ-related posts on this blog here.

Convert array of strings to integers with C# LINQ

Consider the following array of strings:

string[] numbersAsString = new string[] { "3", "1", "2", "4" };

You can easily convert each member and store them in an integer array with just one line of code:

int[] numbersAsInt = numbersAsString.Select(s => int.Parse(s)).ToArray();

You can sort the integers too:

int[] numbersAsInt = numbersAsString.Select(s => int.Parse(s)).OrderBy(s => s).ToArray();

You can view all LINQ-related posts on this blog here.

Filter an array of integers with LINQ C# using a lambda expression

Consider the following array of integers:

int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

Say you want to filter out the odd numbers. One way to achieve this is using LINQ with a lambda expression. You’ll need a delegate that returns a boolean:

public delegate bool IntegerFilter(int i);

The following function accepts an integer array and a delegate and returns the filtered array:

public int[] FilterIntegerArray(int[] ints, IntegerFilter filter)
    {
      List<int> intList = new List<int>;
      foreach (int i in ints)
      {
        if (filter(i))
        {
          intList.Add(i);
        }
      }
      return intList.ToArray();
    }

You can call this method as follows using lambda expression that matches the signature of the delegate:

int[] oddNumbers =
        FilterIntegerArray(nums, i => ((i & 1) == 1) });

You can view all LINQ-related posts on this blog here.

Simple Func delegate example with LINQ in .NET C#

Say you’d like to filter an array of integers:

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

You’re only interested in integers greater than 3. There are many ways to filter an array of T. One of them is using a Func delegate. Func delegates come in the following forms:

public delegate TR Func<TR>();
public delegate TR Func<Arg0, TR>(Arg0 a0);
public delegate TR Func<Arg0, Arg1, TR>(Arg0 a0, Arg1 a1);
.
.
.
public delegate TR Func<Arg0, Arg1, Arg2, Arg3, TR>(Arg0 a0, Arg1 a1, Arg2 a2, Arg3 a3);

…where TR is the return type of function and Arg(x) is the input parameter type. Note that the return type is the last element of the parameter types.

One of the overloaded versions of the LINQ Where operator accepts a Func delegate:

IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<int, bool> predicate);

So we declare our Func:

Func<int, bool> GreaterThanTwo = i => i > 3;

Then we declare our query:

IEnumerable<int> intsGreaterThanTwo = ints.Where(GreaterThanTwo);

We finally enumerate the query:

foreach (int i in intsGreaterThanTwo)
{
        Console.WriteLine(i);
}

You can view all LINQ-related posts on this blog here.

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

ARCHIVED: Bite-size insight on Cyber Security for the not too technical.