LINQ in C# - Examples - GroupBy - Grouping

  • The grouping operators assist with grouping elements of a sequence together by a common key.
  • GroupBy operator return a sequence of IGrouping<K, T> elements.
    • Where K - is key of field type which is used for grouping
    • Where T -  is actual object

GroupBy- Type 1 - with default comparer- Example

class Customer
    {
        public int CustomerID { get; set; }
        public string CustomerType { get; set; }
        public string Name { get; set; }
    }
class Program
    {       
        static void Main(string[] args)
        {
            List<Customer> Customers = new List<Customer> {
                                    new Customer(){ CustomerID=1, Name="XYZ Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=2, Name="ABC Private Limited", CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=3, Name="MS Infotech", CustomerType="Retail" },
                                    new Customer(){ CustomerID=4, Name="Oracle" , CustomerType="WholeSale" },
                                    new Customer(){ CustomerID=5, Name="IBM Hardware Limited", CustomerType="Retail" },
                                 };

         

            IEnumerable<IGrouping<string, Customer>> CustomersGroup = Customers.GroupBy(x => x.CustomerType);
           
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
                
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
        }                              
           
    }
//Output
Group Name:WholeSale

Customers
-------------
ID:1, Name:XYZ Private Limited
ID:2, Name:ABC Private Limited
ID:4, Name:Oracle

Group Name:Retail

Customers
-------------
ID:3, Name:MS Infotech
ID:5, Name:IBM Hardware Limited
  • As you can see from the above example GroupBy returns IGrouping<string, Customer>,in this key of type string because Customer.CustomerType is of type string and the as source type is of type Customer
  • It is not compulsory to put return type as  IEnumerable<IGrouping<string, Customer>>, it can be declared as var or can be return as a List, just for understanding I have used IEnumerable<IGrouping<string, Customer>>
List<IGrouping<string, Customer>> CustomersGroup = Customers.GroupBy(x => x.CustomerType).ToList();
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
  • Both(above/below) versions will return the same result as first Example
var CustomersGroup = Customers.GroupBy(x => x.CustomerType)
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();

GroupBy- Type 2 - with Custom comparer- Example

  • IEqualityComparer<T> Interface allows the implementation of customized equality comparison for collections
  • That is, you can create your own definition of equality for type T, and specify that this definition be used with a collection type that accepts the IEqualityComparer<T> generic interface.
  • Before we look into GroupBy - Type 2, we will discuss about IEqualityComparer interface and how it works
class CustomerEqualityComparer : IEqualityComparer<string>
    {
        public bool Equals(string x, string y)
        {
            if (this.GetHashCode(x) == this.GetHashCode(y))
                return true;
            else
                return false;          
        }

        public int GetHashCode(string obj)
        {
            return obj.Length; // Just any logic to generate hashcode
        }
    }
  • As you can see from above code the IEqualityComparer contains two methods GetHashCode and Equals
    •  GetHashCode- method is just a helper method, as IEqualityComparer<T> generic interface, we are passing string type here as CustomerType is of type string.
    • It is upto us to decide how the hashcode will be generator, 
    • Even without calling this method also we can 
    • Equals - method is the actual method for checking the equality, it is up to us to decide whether we are going to use the GetHashCode or not, for checking the equality.
    • Just for to show how it works I have implemented a dummy logic.

GroupBy- Type 2 - with Custom Equality comparer- Example

IEnumerable<IGrouping<string, Customer>> CustomersGroup = Customers.GroupBy(x => x.CustomerType, new CustomerEqualityComparer());
          
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
  • Any way the result will be the same as the first type, as we didn't do any big change in the Custom Comparer class logic

GroupBy- Type 3 - Example

  • This type is same as the first Type, with the small change the return type of the GroupBy operator
  • In the Type 1 Example, we just specify the group by column, so the return type is the base type of the sequence i.e Customer by default
  • We have a option to specify the return data/type of the object as custom
  • In this example i am going to change the first type slightly and show to how to specify the custom return type.
IEnumerable<IGrouping<string, Customer>> CustomersGroup = Customers.GroupBy(x => x.CustomerType, y => y);
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(Customer C in item)
                {
                    Console.WriteLine($"ID:{C.CustomerID}, Name:{C.Name}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
IEnumerable<IGrouping<string, string>> CustomersGroup = Customers.GroupBy(x => x.CustomerType, y => y.Name);
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(string CustomerName in item)
                {
                    Console.WriteLine($"Name:{CustomerName}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();

GroupBy- Type 4 - Example

  • Type 4 is nothing but a combination of both Type 2 and Type 3
IEnumerable<IGrouping<string, string>> CustomersGroup = Customers.GroupBy(x => x.CustomerType, y => y.Name, new CustomerEqualityComparer());
            foreach (var item in CustomersGroup)
            {
                Console.WriteLine($"Group Name:{item.Key}\n");
               
                Console.WriteLine("Customers");
                Console.WriteLine("-------------");
                foreach(string CustomerName in item)
                {
                    Console.WriteLine($"Name:{CustomerName}");
                }
                Console.WriteLine();
            }
            Console.ReadLine();

No comments:

Post a Comment

Framework Fundamentals - String - Comparing Strings

In comparing two values, the .NET Framework differentiates the concepts of equality comparison and order comparison . Equality compariso...