Selecting a subset of elements in LINQ C# with the SkipWhile operator

The SkipWhile operator is similar to Skip. With Skip we omit the first n elements where n is an integer. With SkipWhile you can define a boolean condition. The elements will be skipped until the condition is true.

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

The following query will keep skipping the items until it finds one which is at least 10 characters long:

IEnumerable<string> res = bands.SkipWhile(s => s.Length < 10);
foreach (string item in res)
{
	Console.WriteLine(item);
}

The first item to be selected and printed on the Console window is “Iron Maiden” as it is exactly 10 characters long. The remaining elements in the array will be selected as the initial condition has been fulfilled.

SkipWhile has an overload where you can specify the loop parameter. The following query will keep skipping items until it finds one which is at least 10 characters long OR the tenth element has been reached:

IEnumerable<string> res2 = bands.SkipWhile((s, i) => s.Length < 10 && i < 10);
foreach (string item in res2)
{
	Console.WriteLine(item);
}

This query yields the same result as the one above as “Iron Maiden” is the 4th element so the “s.Length less than 10” condition has been reached first.

View the list of posts on LINQ here.

Ordering a .NET data sequence with various LINQ operators

A sequence of any object can be easily ordered with the following LINQ operators in .NET:

  • OrderBy
  • ThenBy
  • OrderByDescending
  • ThenByDescending

Consider the following sequence:

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

The first overload of OrderBy lets you specify the property by which to order the elements and they will be sorted by a default comparer. This is how to order the list of bands by the string length:

IEnumerable<string> ordered = bands.OrderBy(band => band.Length);
foreach (string item in ordered)
{
	Console.WriteLine(item);
}

Order by string length

The second overload of OrderBy lets you specify a comparer which will determine the order of elements. The comparer must implement the IComparer of T interface. Say you’d like to order the bands by the number of consonants in their names. The following comparer would do:

public class ConsonantNumberComparer : IComparer<string>
{
	public int Compare(string x, string y)
	{
		int consonantCountStringOne = GetConsonantCount(x);
		int consonantCountStringTwo = GetConsonantCount(y);

		if (consonantCountStringOne < consonantCountStringTwo) return -1;
		if (consonantCountStringOne > consonantCountStringTwo) return 1;
		return 0;
	}

	private int GetConsonantCount(string input)
	{
		char[] consonants = new char[] { 'b', 'c', 'd', 'f', 'g', 'h','k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'z', 'x', 'y' };
		int count = 0;
		foreach (char c in input.ToLower())
		{
			if (consonants.Contains(c))
			{
				count++;
			}
		}

		return count;
	}
}

You can use this comparer as follows:

IEnumerable<string> ordered = bands.OrderBy(band => band, new ConsonantNumberComparer());
foreach (string item in ordered)
{
	Console.WriteLine(item);
}

Order by number of consonants

You can specify additional ordering rules using the ThenBy operator. The following query will order the items by the comparer we’ve just constructed and then in alphabetical order:

IEnumerable<string> ordered = bands.OrderBy(band => band, new ConsonantNumberComparer()).ThenBy(band => band);
foreach (string item in ordered)
{
	Console.WriteLine(item);
}

Order by string length and alphabetical

Don’t use the OrderBy() operator multiple times like this in order to fulfil what ThenBy is doing:

IEnumerable<string> ordered = bands.OrderBy(band => band, new ConsonantNumberComparer()).OrderBy(band => band);

This will first order the items according to the ConsonantNumberComparer and then completely re-order the items in alphabetical order. Therefore the first order by is cancelled out in the final sequence.

The OrderByDescending and ThenByDescending operators do exactly what OrderBy and ThenBy but in reverse order as the names suggest:

IEnumerable<string> ordered = bands.OrderByDescending(band => band, new ConsonantNumberComparer()).ThenByDescending(band => band);
foreach (string item in ordered)
{
	Console.WriteLine(item);
}

Order by string length and alphabetical descending

ThenBy, OrderByDescending and ThenByDescending can also accept an IComparer object just like OrderBy.

View the list of posts on LINQ here.

Summing the elements of a sequence with LINQ C#

Say you have the following numeric sequence:

IEnumerable<int> integers = Enumerable.Range(1, 100);

If you don’t know what the Range operator does, then start here.

You can find the sum of the elements in the sequence using the Sum LINQ operator:

int sum = integers.Sum();

…which gives 5050. The Sum operator obviously only works with numeric elements such as int, long, decimal and double. You can sum specific elements of an object using the overloaded Sum operator.

Take the following objects:

public class Concert
{
	public int SingerId { get; set; }
	public int ConcertCount { get; set; }
	public int Year { get; set; }
}

IEnumerable<Concert> concerts = 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}
			};

You can get the total number of concerts in the collection by specifying the property selector in a lambda expression as follows:

int allConcerts = concerts.Sum(c => c.ConcertCount);

…which yields 557.

View the list of posts on LINQ here.

Selecting a subset of elements in LINQ C# with the Skip operator

The Skip operator is the opposite of Take: it skips the given number of elements in a sequence and selects the rest.

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

We’ll omit the first 10 elements and select the rest:

IEnumerable<string> res = bands.Skip(10);
foreach (string item in res)
{
	Console.WriteLine(item);
}

Skip output

The first element to be selected will be “Chic” as that is the 11th items in the array.

The Skip operator is often used together with Take to allow paging in a data collection. Imagine we have a HTML table where we have 10 items on each page. When the user selects page 2 then we want to show items 11 to 20 in the table. The LINQ query looks like this:

IEnumerable<string> res = bands.Skip(10).Take(10);
foreach (string item in res)
{
	Console.WriteLine(item);
}

Skip operator output

View the list of posts on LINQ here.

Selecting the only element from a single element sequence in .NET C#

Say you have the following Singer object and sequence of Singers:

public class Singer
{
	public int Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public int BirthYear { get; set; }
}

IEnumerable<Singer> singers = new List<Singer>() 
		{
			new Singer(){Id = 1, FirstName = "Freddie", LastName = "Mercury", BirthYear=1964}
			, new Singer(){Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954}
			, new Singer(){Id = 3, FirstName = "Chuck", LastName = "Berry", BirthYear = 1954}
			, new Singer(){Id = 4, FirstName = "Ray", LastName = "Charles", BirthYear = 1950}
			, new Singer(){Id = 5, FirstName = "David", LastName = "Bowie", BirthYear = 1964}
		};

You can use the Single operator to get the only result of an element selector. You can write in two different ways which are functionally the same:

Singer singer = singers.Where(s => s.Id == 2).Single();
Console.WriteLine(singer.LastName);

…or…

Singer singer = singers.Single(s => s.Id == 2);
Console.WriteLine(singer.LastName);

Both will select Elvis Presley. The query was successful because the element selector lambda expression resulted in a sequence with a single element. The Single operator extracted that one element from the – very short – sequence. If it finds more than one element matching the filter or if it finds nothing then it will throw an exception:

Singer singer = singers.Single(s => s.Id == 200);
Singer singer = singers.Single(s => s.Id < 4);

The first line throws an invalid operation exception as the resulting sequence contained 0 elements. The second line again throws the same type of exception because the element selector yielded more than one element.

You can use the operator SingleOrDefault to avoid the problem encountered with 0 elements:

Singer singer = singers.SingleOrDefault(s => s.Id == 200);
Console.WriteLine(singer == null ? "No such singer" : singer.LastName);

View the list of posts on LINQ here.

Building an integer sequence using the Range operator in LINQ C#

Say you need a list of integers from 1 to 10. The traditional way is the following:

List<int> traditional = new List<int>();
for (int i = 1; i <= 10; i++)
{
	traditional.Add(i);
}

There’s a more concise way to achieve this with the static Range method which accepts two parameters. The first integer in the sequence and a count variable which defines the number of elements in the list. The step parameter is 1 by default and cannot be overridden:

IEnumerable<int> intRange = Enumerable.Range(1, 10);
foreach (int i in intRange)
{
	Console.WriteLine(i);
}

This will print the integers from 1 to 10.

Say you need an integer list from 100 to 110 inclusive:

IEnumerable<int> intRange = Enumerable.Range(100, 11);

View the list of posts on LINQ here.

Selecting a subset of elements in LINQ C# with the TakeWhile operator

The TakeWhile extension method in LINQ is similar to Take. With Take you can specify the number of elements to select from a sequence. In the case of TakeWhile we can specify a condition – a boolean function – instead. The operator will take elements from the sequence while the condition is true and then stop.

Data collection:

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

We’ll keep selecting the items until we find one that starts with an ‘E’:

IEnumerable<string> res = bands.TakeWhile(b => b[0] != 'E');
foreach (string s in res)
{
	Console.WriteLine(s);
}

This will print all bands from “ACDC” to and including “Chic”. The last item to be selected will be “Chic”, as the one after that, i.e. Eurythmics starts with an ‘E’.

There’s an overload of TakeWhile where you can pass in the index variable of the loop. The following query will keep selecting the bands until we find one that starts with an ‘E’ OR the loop index exceeds 8:

IEnumerable<string> res2 = bands.TakeWhile((b, i) => b[0] != 'E' && i < 8);
foreach (string s in res2)
{
	Console.WriteLine(s);
}

This time Oasis is the last item to be selected as that is the 8th item, so the “i less than 8” condition was reached first.

View the list of posts on LINQ here.

Finding the minimum value in a sequence with LINQ C#

Finding the minimum value in a sequence can be performed using the Min LINQ operator. In it simplest, parameterless form it works on numeric sequences like this:

List<int> integers = new List<int>() { 54, 23, 76, 123, 93, 7, 3489 };
int intMin = integers.Min();

…which gives 7.

Applying the operator on a list of strings gives the alphabetically minimum value in the list:

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"};
string stringMin = bands.Min();

…which yields Abba.

The operator can be applied to sequences of custom objects:

public class Singer
{
	public int Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public int BirthYear { get; set; }
}

IEnumerable<Singer> singers = new List<Singer>() 
{
	new Singer(){Id = 1, FirstName = "Freddie", LastName = "Mercury", BirthYear=1964}
	, new Singer(){Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954}
	, new Singer(){Id = 3, FirstName = "Chuck", LastName = "Berry", BirthYear = 1954}
	, new Singer(){Id = 4, FirstName = "Ray", LastName = "Charles", BirthYear = 1950}
	, new Singer(){Id = 5, FirstName = "David", LastName = "Bowie", BirthYear = 1964}
};

int minSingerBirthYear = singers.Min(s => s.BirthYear);

We applied a selector function to find the minimum birth year, i.e. 1950. We can find the minimum first name alphabetically speaking:

String minSingerName = singers.Min(s => s.FirstName);

…which gives “Chuck”.

View the list of posts on LINQ here.

Getting the first element from a sequence in LINQ C#

Say you have the following object sequence:

public class Singer
{
	public int Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public int BirthYear { get; set; }
}

IEnumerable<Singer> singers = new List<Singer>() 
			{
				new Singer(){Id = 1, FirstName = "Freddie", LastName = "Mercury", BirthYear=1964}
				, new Singer(){Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954}
				, new Singer(){Id = 3, FirstName = "Chuck", LastName = "Berry", BirthYear = 1954}
				, new Singer(){Id = 4, FirstName = "Ray", LastName = "Charles", BirthYear = 1950}
				, new Singer(){Id = 5, FirstName = "David", LastName = "Bowie", BirthYear = 1964}
			};

If you just want to get the very first element from this sequence with no query then you can use the First operator:

Singer singer = singers.First();
Console.WriteLine(singer.LastName);

This will select Freddie Mercury from the list. You can also send an item selector to get the first element which matches the query:

Singer singer = singers.First(s => s.Id == 2);
Console.WriteLine(singer.LastName);

…which returns Elvis Presley.

A caveat is that the First operator throws an InvalidOperationException if there’s no single matching record:

Singer singer = singers.First(s => s.Id == 100);

To avoid this scenario you can use the FirstOrDefault operator which returns the default value of the required object if there’s no matching one. Therefore “singer” in the above example will be null:

Singer singer = singers.FirstOrDefault(s => s.Id == 100);
Console.WriteLine(singer == null ? "No such singer" : singer.LastName);

…which prints “No such singer”.

View the list of posts on LINQ here.

Retrieving an element from a sequence with an index in LINQ C#

Say you have the following Singer object and sequence of Singers:

public class Singer
{
	public int Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public int BirthYear { get; set; }
}

IEnumerable<Singer> singers = new List<Singer>() 
		{
			new Singer(){Id = 1, FirstName = "Freddie", LastName = "Mercury", BirthYear=1964}
			, new Singer(){Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954}
			, new Singer(){Id = 3, FirstName = "Chuck", LastName = "Berry", BirthYear = 1954}
			, new Singer(){Id = 4, FirstName = "Ray", LastName = "Charles", BirthYear = 1950}
			, new Singer(){Id = 5, FirstName = "David", LastName = "Bowie", BirthYear = 1964}
		};

Say you want to get to the second element of the singers sequence. You can use the ElementAt operator to achieve that. As all arrays and lists are 0 based, then the second element has index = 1:

Singer singer = singers.ElementAt(1);
Console.WriteLine(singer.LastName);

The operator has found Elvis Presley. If there’s no element at the specified index then an ArgumentOutOfRangeException is thrown. To avoid that you can use the ElementAtOrDefault operator instead:

Singer singer = singers.ElementAtOrDefault(100);
Console.WriteLine(singer == null ? "No such singer" : singer.LastName);

…which prints “No such singer”.

View the list of posts on LINQ 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.