LINQ SelectMany and IGrouping


Introduction

This post is prompted by the the following:

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 
            }
    
        }
    
  • Sample 1: shows the way that SelectMany can unwrap a list of lists into a list.
  • Sample 2: shows an interesting way of detecting duplicates. This solution returns a list of the strings with more than 1 occurrence (Skip(1)), as a list of n-1 copies of string (where n is the number of times that string occurs). So if you just want the duplicated string (occurring only once), put a Distinct() after the SelectMany. This example also invokes an interesting property of the GroupBy and what is returned the IGrouping interface, I’ll comment on that below.
  • Sample 3: Is a demonstration of a lambda expression working within a class which contains a list.  

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). 

 

About these ads

, , , , , , , , ,

  1. #1 by Romiko Derbynew on February 10, 2012 - 2:12 pm

    Thanks :)

  1. LINQ Pivot, or Crosstab, Extension Method « Craig's Eclectic Blog
  2. Yield Return: Uses, Abuses and “Rules of Thumb” « Craig's Eclectic Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: