If you are an experienceg .NET developer then you might be aware of LINQ and it's advantages. Yes it's a uniform query language to get and filter data from various data sources.

Fine, but LINQ is beyond that and we can combine various functions and operators associated with a LINQ query. Believe it or not, by using those functions we can make LINQ more robust for data processing and manipulation queries.

This article shows various functions and operators associated with LINQ and we will see how it makes data processing operations simple.

We can categorize the operators in many categories. Let's see a few of them.

Aggregation

Here we will understand various LINQ operators that will work on data, let's start with aggregation. Here is a few examples.

  1. namespace ConsoleApp
  2. {
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. //Example of aggregration
  8. int[] data = { 1, 2, 3, 4, 5 };
  9. //Sum of numbers
  10. Console.WriteLine(data.Sum()); //ans:15
  11. //Average of numbers
  12. Console.WriteLine(data.Average()); //Ans :3
  13. //Max of numbers
  14. Console.WriteLine(data.Max()); //Ans :5
  15. String[] strdata = {"1","two","three","four","five"};
  16. //Item with minimum length
  17. Console.WriteLine(strdata.Min()); //Ans :1
  18. //Item with minimum character(same as above)
  19. Console.WriteLine(strdata.Min(f=>f.Length)); //Ans:1
  20. //Items with maximum character
  21. Console.WriteLine(strdata.Max(f => f.Length)); //Ans :5
  22. Console.ReadLine();
  23. }
  24. }
  25. }

Concatination

A Concatenation operation takes place when we want to combine more than one element. In this example we have used the Concat function to combine two arrays. I believe many developers don't know the shortcut to combine two arrays, sometimes they use foreach or some kind of iterative statement to do the same job.

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. public class Program
  5. {
  6. public static void Main(string[] args)
  7. {
  8. //First array
  9. int[] data = { 1, 2, 3 };
  10. //Concatination with another array
  11. int[] result = data.Concat(new int[] { 4, 5, 6 }).ToArray();
  12. //result 1,2,3,4,5,6
  13. }
  14. }

Conversion

The dictionary meaning of conversion is applicable here. To convert one type to another type, we can use a Cast parameterized function. In this example I am showing how to convert from IEnumerable to a list and an array.

  1. public static void Main(string[] args)
  2. {
  3. object[] data = { "1", "2", "3", "4", "5" };
  4. //Cast to Ienumerable<string>
  5. IEnumerable<string> strEnum = data.Cast<string>();
  6. //Cast to List
  7. List<string> strList = data.Cast<string>().ToList();
  8. //Cast to Array
  9. string[] strArray = data.Cast<string>().ToArray();
  10. }

Element operation

It's very common in applications that we sometimes need a direct element, direct in the sense that we want to pick the element by it's index or by a query. There are many functions available with which we can combine a lambda expression to simplify our job.

  1. public static void Main(string[] args)
  2. {
  3. int[] data = { 1, 2, 3, 4, 5 };
  4. data.ElementAt(10); //Error
  5. data.ElementAtOrDefault(10); //null
  6. data.First(); //1
  7. string[] name = {"sourav","Ram","Shyam"};
  8. //First three letter name
  9. name.First(m => m.Length == 3); // Ram
  10. //First name which is greater then 3
  11. name.First(m => m.Length > 3); //sourav
  12. //Last element of array
  13. name.Last(); //Shyam
  14. //Get one element
  15. name.Single(); //Exception. More than one element
  16. //Try to get single element if empty array then return null
  17. name.SingleOrDefault(); //Exception: More than one element
  18. //try to get item whose length is 10
  19. name.SingleOrDefault(m => m.Length == 10); //null
  20. }

Equality

Equality checking between lists or some kind of collection is another common requirement in applications. If we want to check whether or not the words are sequentially arranged then we can use the SequenceEqual function. Although there are many I will mention the uncommon one.

  1. public static void Main(string[] args)
  2. {
  3. //Equality checking.
  4. string[] words = { "sourav", "Ram", "Shyam" };
  5. //Check whether all items are present sequencially or not
  6. words.SequenceEqual(new[] { "sourav", "Ram", "Shyam" }); //Ans : True
  7. //Case is different
  8. words.SequenceEqual(new[] { "SOURAV", "RAM", "SHYAM" }); //False
  9. //Ignore cases in checking
  10. words.SequenceEqual(new[] { "SOURAV", "RAM", "SHYAM"}, StringComparer.OrdinalIgnoreCase); //True
  11. }

Partitioning

This operation divides the entire set into two partitions and picks one of them. In this example we will see few functions combine with a lambda expression.

  1. public static void Main(string[] args)
  2. {
  3. string[] name = { "one","two", "three" };
  4. // take two elements from list
  5. name.Take(2).ToList<string>(); // one two
  6. //Skip first one element in list
  7. name.Skip(1).ToList<string>(); //two three
  8. //Take eleents whose length is 3
  9. name.TakeWhile(f => f.Length == 3); //one two
  10. //Skil element when length is less than 4
  11. name.SkipWhile(f => f.Length < 4); // three
  12. Console.ReadLine();
  13. }

Projection

This operation is needed when we want to take a certain part from a collection. Here, we are taking part of a name array by length, by its index position. Have a look at the following example.

  1. public static void Main(string[] args)
  2. {
  3. string[] name = { "one","two", "three" };
  4. //Find lenght if all element.
  5. name.Select(f => f.Length); // 3 3 4
  6. //print element with index
  7. name.Select((a, b) => b.ToString() + ":" + a); // 0 : one 1: two 2:three
  8. //Print items nuber of times by it's index
  9. //For example one is in 0th position - so not printed
  10. //two is in 1st position - so printed one time
  11. //Three is in 2nd position - so printed 2 times
  12. name.SelectMany((a, b) => Enumerable.Repeat(a, b)).ToArray(); //two three three
  13. Console.ReadLine();
  14. }

Set based operation

A set based operation is not a very common in day-to-day programming, but it's useful to understand an overview of the functions. It's very similar to a normal math set operation. Just have a quick look at the following example.

  1. public static void Main(string[] args)
  2. {
  3. //set based operation
  4. string[] first = { "a", "b", "b" ,"c" };
  5. string[] second = { "c", "d", "e" };
  6. //Select unique element
  7. first.Distinct(); // a,b,c
  8. //Intersect -Take common
  9. first.Intersect(second); // c
  10. //Union - Get all unique element
  11. first.Union(second); //a b c d e
  12. //Except
  13. first.Except(second); // a b
  14. Console.ReadLine();
  15. }

Filtering

Filtering is very essential in day-to-day programming. In this example we will see a few useful filtering functions associated with lambda expressions.

  1. public static void Main(string[] args)
  2. {
  3. //Sorting
  4. string[] name = {"one","two","three" };
  5. //Order collection alphabetically- First character
  6. name.OrderBy(f => f).ToArray(); //one three two
  7. //arrange alphabetically on second character
  8. name.OrderBy(f => f[1]); // three one two
  9. //Order by length
  10. name.OrderBy(f => f.Length); //one two three
  11. //Order by length descending
  12. name.OrderByDescending(f => f.Length);
  13. //First by length then Descending.
  14. name.OrderBy(f => f.Length).ThenByDescending(f => f); //two one three
  15. Console.ReadLine();
  16. }

Conclusion

This article showed various functions associated with LINQ and lambda expressions. It's good to understand those functions to reduce the amount of code and program complexity.