Friday, March 13, 2009

Grouping with Linq Igrouping

Now a days no one uses arrays any more, the reason why, because they are a pain to work with and seriously, why would you when we have the generic List<T> collection.
If you are using object collections that implement IEnumerable like List<T>, List(Of T)  in VB, you are in a world of joy. And if you are using Linq then you are in a world of joy in Christmas!

If there is one technology that have had an impact  on my coding then it would be Linq. Things that where a pain to do like parsing an XML file and doing loops and if statements for selecting elements from an array have been reduced to some lines of code.

A simple example of this would be to select a subset of objects from a list. Say we have an instantiated collection of car objects from our car database, (why always cars??).

public List<Car> GetBySoldYear(DateTime year){
var cars = from c in GetCarList()
where c.YearSold.Year == year.Year
select c;
return cars.ToList();
}


This snipped returns all cars that where sold a specific date. So instead of iterating the collection doing if checks and copying the matching results to a new list, we simply express our feelings in a nice SQL like syntax. Well the hole select statement is in reverse but you get it. The reverse thingee is so that the compiler has a chance to serve you with some nice intellisense as you type. That you don’t get from the SQL query editor!



Now for another scenario, this is maybe more uncommon but when you get there, Linq is to the rescue. I’m talking about when you want to get a grouped result, like, group the cars by year sold.

Now when doing this, if you are used to the SQL results from a group by query, this is nothing like it. The result from a group by is a flat table. With Linq grouping you get a IEnumerable<IGrouping<Key,T>>, where IGrouping<Key,T> is a collection all by it’s self. The Key is the value you did the group by on and T the actual object that matched the criteria. 
in this case the result is a IEnumerable<IGrouping<DateTime, Car>>. The code for this query looks like this



public IEnumerable<IGrouping<DateTime, Car>> GroupedByYear(){
var carlist = GetCarList();
var grouped = from car in carlist
group car by car.YearSold;
return grouped;
}


If you would like to get the result of this you simply iterate through the IGrouping<DateTime, Car> collection, like so:



public void PrintModelsPerYear()
{
foreach (IGrouping<DateTime, Car> cars in GroupedByYear()){
Console.WriteLine("YearSold: {0} - Count {1}", cars.Key, cars.Count());
}
}


Remember that the Key will be the value of the filtered group, so the output will look like this:

YearSold: 2009-01-01 00:00:00 - Count 2
YearSold: 2005-01-01 00:00:00 - Count 2
YearSold: 1985-01-01 00:00:00 - Count 1


Here you can download the code for this post



Technorati-taggar: ,,,,