Friday, April 10, 2015

Linq Query Examples - I

1. Consider the following string array.
string[] countries = { "India", "US", "UK", "Canada", "Australia" };

We want to combine all these strings into a single comma separated string. The output of the program should be as shown below. 
India, US, UK, Canada, Australia
 Ans:
        string result = countries.Aggregate((a, b) => a + ", " + b);

*Print all the ProductNames in comma separated list of a given category
string productNames = db.Categories.Where( x=> x.categoryId ==1)
                                         .SelectMany(x=> x.Products.Select(p=>p.ProductName)).ToArray()
                                         .Aggregate( (a,b) => a + ", " + b) );


2.  Consider the following integer array

      int[] Numbers = { 2, 3, 4, 5 };
    Compute the product of all numbers

    int result = Numbers.Aggregate((a, b) => a * b);  


3. What is a Predicate?
A predicate is a function to test each element for a condition
In the following example, the Lambda expression (num => num % 2 == 0) runs for each element in List<int>. If the number is divisible by 2, then a boolean value true is returned otherwise false.

            List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 
            IEnumerable<int> evenNumbers = numbers.Where(num => num % 2 == 0);

As shown in debug mode during its execution,the predicate expects an int input parameter and returns a boolean value. The lambda expression that is passed operates on an int type and should return boolean, otherwise there will be compile time error.






Restriction Operators in LINQ

So this means, the line below from the above example

IEnumerable<int> evenNumbers = numbers.Where(num => num % 2 == 0);

can be rewritten as shown below
Func<int, bool> predicate = i => i % 2 == 0;
IEnumerable<int> evenNumbers = numbers.Where(predicate);
 Or like below:
IEnumerable<int> evenNumbers = numbers.Where(num => IsEven(num));
    
public static bool IsEven(int number)
        {
            if (number % 2 == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }


The int parameter of the predicate function represents the index of the source element
 The following program prints the index position of all the even numbers
   List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            IEnumerable<int> evenNumberIndexPositions = numbers
                .Select((num, index) => new { Number = num, Index = index })
                .Where(x => x.Number % 2 == 0)
                .Select(x => x.Index);
            foreach (int evenNumber in evenNumberIndexPositions)
            {
                Console.WriteLine(evenNumber);
            }




SelectMany Operator belong to Projection Operators category. It is used to project each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence.  
 Consider the following Student class. Subjects property in this class is a collection of strings.
public class Student
{
    public string Name { get; set; }
    public string Gender { get; set; }
    public List<string> Subjects { get; set; }     public static List<Student> GetAllStudetns()
     {
        List<Student> listStudents = new List<Student>
        {
            new Student
            {
                Name = "Tom",
                Gender = "Male",
                Subjects = new List<string> { "ASP.NET", "C#" }
            },
            // add few more students like this.
    
        };
        return listStudents;
    }

 Projects all subject strings of a given a student to an IEnumerable<string>
IEnumerable<string> allSubjects = Student.GetAllStudetns().SelectMany(s => s.Subjects);
 Output:


selectmany c# example 
Rewrite above, using SQL like syntax. When using SQL like syntax style, we don't use SelectMany, instead we will have an additional from clause, which will get it's data from the results of the first from clause.



IEnumerable<string> allSubjects = from student in Student.GetAllStudetns()
                                                            from subject in student.Subjects
                                                            select subject;



Projects each string to an IEnumerable<char>

string[] stringArray =
{
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    "0123456789"
};
IEnumerable<char> result = stringArray.SelectMany(s => s);
foreach (char c in result)
{
    Console.WriteLine(c);
}
 Sql like syntax:
IEnumerable<char> result = from s in stringArray
                                                from c in s
                                                select c;


 Selects only the distinct subjects

IEnumerable<string> allSubjects = Student.GetAllStudetns()
                                                                   .SelectMany(s => s.Subjects).Distinct();
 using SQL like syntax. 
IEnumerable<string> allSubjects = (from student in Student.GetAllStudetns()
                                                             from subject in student.Subjects
                                                             select subject).Distinct();
  Selects student name along with all the subjects

var result = Student.GetAllStudetns().SelectMany(s => s.Subjects, (student, subject) =>
    new { StudentName = student.Name, Subject = subject });
foreach (var v in result)
{
    Console.WriteLine(v.StudentName + " - " + v.Subject);
}
using SQL like syntax. 

var result = from student in Student.GetAllStudetns()
                    from subject in student.Subjects
                    select new { StudnetName = student.Name, Subject = subject };


 LINQ GROUP BY:
GroupBy operator belong to Grouping Operators category. This operator takes a flat sequence of items, organize that sequence into groups (IGrouping<K,V>) based on a specific key and return groups of sequences. 
 
In short, GroupBy creates and returns a sequence of IGrouping<K,V>
 Consider Employee class
 public class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
    public string Department { get; set; }
    public int Salary { get; set; }
 
    public static List<Employee> GetAllEmployees()
    {
      
       return new List<Employee>()
        {
            new Employee { ID = 1, Name = "Mark", Gender = "Male",
                                         Department = "IT", Salary = 45000 }
            // add few more employees..
        }
    }
}
 Example 1: Get Employee Count By Department

var employeeGroup = from employee in Employee.GetAllEmployees()
                                group employee by employee.Department;
foreach (var group in employeeGroup)
{
    Console.WriteLine("{0} - {1}", group.Key, group.Count());
}
 Example 2: Get Employee Count By Department and also each employee and department name
var employeeGroup = from employee in Employee.GetAllEmployees()
                                      group employee by employee.Department;
foreach (var group in employeeGroup)
{
    Console.WriteLine("{0} - {1}", group.Key, group.Count());
    Console.WriteLine("----------");
    foreach (var employee in group)
    {
        Console.WriteLine(employee.Name + "\t" + employee.Department);
    }
    Console.WriteLine(); Console.WriteLine();
}
 Example 3: Get Employee Count By Department and also each employee and department name. Data should be sorted first by Department in ascending order and then by Employee Name in ascending order.
var employeeGroup = from employee in Employee.GetAllEmployees()
                                      group employee by employee.Department into eGroup
                                      orderby eGroup.Key
                                      select new
                                      {
                                           Key = eGroup.Key,
                                           Employees = eGroup.OrderBy(x => x.Name)
                                      };
foreach (var group in employeeGroup)
{
    Console.WriteLine("{0} - {1}", group.Key, group.Employees.Count());
    Console.WriteLine("----------");
    foreach (var employee in group.Employees)
    {
        Console.WriteLine(employee.Name + "\t" + employee.Department);
    }
    Console.WriteLine(); Console.WriteLine();
}

Output:
groupby linq c# example
GROUP BY MULTIPLE KEYS IN LINQ
In LINQ, an anonymous type is usually used when we want to group by multiple keys.
 Consider the Employee Class used above.

Example 1: Group employees by Department and then by Gender. The employee groups should be sorted first by Department and then by Gender in ascending order. Also, employees within each group must be sorted in ascending order by Name.



var employeeGroups = Employee.GetAllEmployees()
                                        .GroupBy(x => new { x.Department, x.Gender })
                                        .OrderBy(g => g.Key.Department).ThenBy(g => g.Key.Gender)
                                        .Select(g => new
                                        {
                                            Dept = g.Key.Department,
                                            Gender = g.Key.Gender,
                                            Employees = g.OrderBy(x => x.Name)
                                        });
foreach(var group in employeeGroups)
{
    Console.WriteLine("{0} department {1} employees count = {2}",
        group.Dept, group.Gender, group.Employees.Count());
    Console.WriteLine("--------------------------------------------");
    foreach (var employee in group.Employees)
    {
        Console.WriteLine(employee.Name + "\t" + employee.Gender
            + "\t" + employee.Department);
    }
    Console.WriteLine(); Console.WriteLine();
}

Output:
linq group by multiple keys


 Example 2: Rewrite Example 1 using SQL like syntax

var employeeGroups = from employee in Employee.GetAllEmployees()
                                        group employee by new
                                        {
                                             employee.Department,
                                             employee.Gender
                                        } into eGroup
                                        orderby eGroup.Key.Department ascending, 
                                                      eGroup.Key.Gender ascending
                                        select new
                                        {
                                             Dept = eGroup.Key.Department,
                                             Gender = eGroup.Key.Gender,
                                             Employees = eGroup.OrderBy(x => x.Name)
                                        };

0 comments:

Post a Comment

Twitter Delicious Facebook Digg Stumbleupon Favorites More