Collection methods id LINQ
Collection
methods
Using LINQ, you can modify existing collections, or collections created using other
LINQ queries. LINQ provides you a set of functions that can be applied to collections.
These functions can be grouped into the following types:
- Set functions - functions that can be used for collection
manipulation operations like merging, intersection, reverse ordering,
etc.,
- Element function - functions that can be used to take particular elements from collections,
- Conversion functions - functions used to convert a type of collection to another,
- Aggregation functions - SQL-like functions that enable you to find a
maximum, sum, or average value of some field in collections,
- Quantifier functions - used to quickly traverse through a collection.
These functions are described in the following sections.
Set operators enable you to manipulate collections and use standard
set operations like unions, intersects, etc. LINQ set operators are:
- Distinct - used to extract distinct elements from a collection,
- Union - creates a collection that represents the union of two existing collections,
- Concat - add elements from one collection to another collection,
- Intersect - creates a collection that contains elements that exist in both collections,
- Except - creates a collection that contains elements that exist in one, but do not exist in another collection,
- Reverse - creates a copy of a collection with elements in reversed order,
- EquallAll - checks whether two collections have the same elements in the same order,
- Take - this function takes a number of elements from one collection, and places them in
a new collection,
- Skip - this function skips a number of elements in a collection,
Assuming that the
booksByTitle and
filteredBooks collection are created in previous examples,
the following code finds all books in
booksByTitle
that do not exist in
filteredBooks, and reverses their order.
IEnumerable<Book> otherBooks = booksByTitle.Except(filteredBooks);
otherBooks = otherBooks.Reverse();
foreach (Book book in otherBooks)
Console.WriteLine("Other book - {0} ", book.Title);
In the following example,
booksByTitle and
filteredBooks are concatenated and
the number of elements and number of distinct elements is shown.
IEnumerable<Book> mergedBooks = booksByTitle.Concat(filteredBooks);
Console.WriteLine("Number of elements in merged collection is {0}", mergedBooks.Count());
Console.WriteLine("Number of distinct elements in merged collection is {0}", mergedBooks.Distinct().Count());
Paging example
In this example is shown an example of client side paging using the
Skip(int) and
Take(int) methods. Assuming that there are ten books per page,
the first three pages are skipped using
Skip(30) (ten books per page placed on three pages), and all books that should be shown on
the fourth page are taken using
Take(10). An example code is:
IEnumerable<Book> page4 = booksByTitle.Skip(30).Take(10);
foreach (Book book in page4)
Console.WriteLine("Fourth page - {0} ", book.Title);
There is also an interesting usage of the
Skip/
Take functions in the
SkipWhile/
TakeWhile form:
IEnumerable<Book> page1 = booksByTitle.OrderBy(book=>book.Price)
.SkipWhile(book=>book.Price<100)
.TakeWhile(book=>book.Price<200);
foreach (Book book in page1)
Console.WriteLine("Medium price books - {0} ", book.Title);
In this example, books are ordered by price, all books with price
less than 100 are skipped, and all books with price less than 200 are
returned.
This way all books with price between 100 and 200 are found.
There are several useful functions that can be applied when you need to extract
a particular element from a collection:
First - used to find the first element in a collection. Optionally you can pass
a condition to this function in order to find the first element that satisfies
the condition.
FirstOrDefault - used to find the first element in a collection. If that kind of element cannot be found,
the default element for that type (e.g., 0 or null) is returned.
ElementAt - used to find the element at a specific position.
The following example shows the usage of the
FirstOrDefault and
ElementAt functions:
Book firstBook = books.FirstOrDefault(b=>b.Price>200);
Book thirdBook = books.Where(b=>b.Price>200).ElementAt(2);
Note that you can apply functions either on the collection, or on the result of some other LINQ function.
There are a few conversion functions that enable you to convert the
type of one collection to another. Some of these functions are:
ToArray - used to convert elements of collection IEnumerable<T> to array of elements
<T>.
ToList - used to convert elements of collection IEnumerable<T> to list
List<T>.
ToDictionary - used to convert elements of a collection to a
Dictionary. During conversion, keys and values must be specified.
OfType - used to extract the elements of the collection IEnumerable<T1> that implements
the interface/class T2, and put them in the collection IEnumerable<T2>.
The following example shows the usage of the
ToArray and
ToList functions:
Book[] arrBooks = books.ToArray();
List<Book> lstBook = books.ToList();
ToDictionary is an interesting method that enables you to quickly index
a list by some field. An example of such a kind of query is shown in the following listing:
Dictionary<string, Book> booksByISBN = books.ToDictionary(book => book.ISBN);
Dictionary<string, double> pricesByISBN = books.ToDictionary( book => book.ISBN,
book=>book.Price);
If you supply just one lambda expression,
ToDictionary will use it as a key of new dictionary while
the elements will be the objects. You can also supply
lambda expressions for both key and value and create a custom dictionary. In the example above,
we create a dictionary of books indexed by the ISBN key, and a dictionary of prices indexed by ISBN.
In each collection, you can find a number of logical functions that can be used to quickly travel through
a collection and check for some condition.
As an example, some of the functions you can use are:
Any - checks whether any of the elements in the collection satisfies
a certain condition.
All - checks whether all elements in the collection satisfies a certain condition.
An example of usage of functions is shown in the following example:
if(list.Any(book=>book.Price<500))
Console.WriteLine("At least one book is cheaper than 500$");
if(list.All(book=>book.Price<500))
Console.WriteLine("All books are cheaper than 500$");
In the example above, the
All and
Any functions will check whether the condition that price is less than 500 is satisfied for books in the list.
Aggregation functions enable you to perform aggregations on elements
of a collection. Aggregation functions that can be used in LINQ are
Count, Sum, Min, Max, etc.
The following example shows the simple usage of some aggregate functions applied to
an array of integers:
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
Console.WriteLine("Count of numbers greater than 5 is {0} ", numbers.Count( x=>x>5 ));
Console.WriteLine("Sum of even numbers is {0} ", numbers.Sum( x=>(x%2==0) ));
Console.WriteLine("Minimum odd number is {0} ", numbers.Min( x=>(x%2==1) ));
Console.WriteLine("Maximum is {0} ", numbers.Max());
Console.WriteLine("Average is {0} ", numbers.Average());
As you can see, you can use either standard aggregation functions, or you can preselect
a subset using a lambda condition.