Introduction
This post is prompted by the the following:
- post by Nick Olsen, titled A Visual Look At The LINQ SelectMany Operator,
- the reference he cited by Justin Etheredge titled, A Visual Look At The LINQ SelectMany Operator, and
- my ignorance of the power of the SelectMany LINQ extension method.
Some Examples of SelectMany
The following C# code demonstrates SelectMany being used in a coupe of different ways. I’ve collated example from a couple of sources here (Nick’s Blog, MSDN, and StackOverflow). They demonstrate a couple of different ways to use the SelectMany LINQ extension method.
namespace SelectMany1 { class PetOwner { public string Name { get; set; } public List<String> Pets { get; set; } } class Program { static void Main(string[] args) { Sample1(); // Taken from Nick Olsen's blog http://nickstips.wordpress.com/2010/07/26/linq-flatten-a-list-of-lists/ Sample2(); // Taken from Sample3(); // Taken from MSDN http://msdn.microsoft.com/en-us/library/bb534336.aspx } private static void Sample3() { PetOwner[] petOwners = { new PetOwner { Name="Higa, Sidney", Pets = new List<string>{ "Scruffy", "Sam" } }, new PetOwner { Name="Ashkenazi, Ronen", Pets = new List<string>{ "Walker", "Sugar" } }, new PetOwner { Name="Price, Vernette", Pets = new List<string>{ "Scratches", "Diesel" } } }; // Query using SelectMany(). IEnumerable<string> query1 = petOwners.SelectMany(petOwner => petOwner.Pets); Console.WriteLine("Using SelectMany():"); // Only one foreach loop is required to iterate // through the results since it is a // one-dimensional collection. foreach (string pet in query1) { Debug.WriteLine(pet); } } private static void Sample1() { List<List<string>> listOfLists = new List<List<string>>(); listOfLists.Add(new List<string>() { "a", "b", "c" }); listOfLists.Add(new List<string>() { "d", "e", "f" }); listOfLists.Add(new List<string>() { "g", "h", "i" }); var flattenedList = listOfLists.SelectMany(x => x); Debug.WriteLine("Sample 1"); foreach (string s in flattenedList) Debug.Write(s + " "); Debug.WriteLine(" "); //Sample 1 //a b c d e f g h i } private static void Sample2() { // Finding duplicates in a list of string List<String> list = new List<String> { "6", "1", "2", "4", "6", "5", "1" }; var duplicates = list.GroupBy(s => s).SelectMany(grp => grp.Skip(1)); Debug.WriteLine("Sample 2"); foreach (string s in duplicates) Debug.Write(String.Format("{0} ", s)); Debug.WriteLine(" "); //Sample 2 //6 1 } }
IGrouping – The output from LINQ GroupBy
This is the output from the LINQ GroupBy extension method. The example 2 lead me to ponder “How does it work?”. Having worked with (around) the LINQ GroupBy extension method previously, I knew that there was a Key property, and a list of contributors to the group. So, how did the Skip(1) work?
It turns out that IGrouping is a bit of an “interesting animal”. The description of the interface is as follows:
public interface IGrouping<out TKey, out TElement> : IEnumerable, IEnumerable
The IEnumerableis the key to how the Skip(1) works. The GroupBy result is being read as series of list, one for each of the keys (I think, I could be wrong).
#1 by Romiko Derbynew on February 10, 2012 - 2:12 pm
Thanks