Jump to content

C# Advanced Sorting with LINQ

- - - - -

  • Please log in to reply
4 replies to this topic

#1
chili5

chili5

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 7,247 posts
  • Programming Language:Java, C#, PHP
  • Learning:C, C++, C#, PHP, Transact-SQL, Assembly, Scheme
Advanced Sorting using LINQ

In more complicated cases we might want to sort data by more than one field at the same time. For example: sort a list of people in increasing order by height then in decreasing order by age. To do this we will make of OrderBy and two new methods ThenBy and ThenByDescending. ThenBy and OrderBy are used to sort in ascending order where as OrderByDescending and ThenByDescending are used to sort in descending order.

For this tutorial we will be dealing with person objects with the following fields:
  • Id
  • Age
  • Height
  • RegisteredDate
First, we need to create a C# class to represent all this information:

  
class Person	{
		public int Id { get; set; }
		public double Height ID{ get; set; }
		public int Age { get; set; }
		public DateTime RegisteredDate { get; set; }
	}

The use of get and set automatically make a function to return the value and to set the value.

To demonstrate various ways of sorting we need a decent data set that we can use.

[TABLE="class: grid, width: 650"]
[TR]
[TD]ID[/TD]
[TD]Age[/TD]
[TD]Height[/TD]
[TD]RegisteredDate[/TD]
[/TR]
[TR]
[TD]0[/TD]
[TD]5[/TD]
[TD]10[/TD]
[TD]2011-03-3[/TD]
[/TR]
[TR]
[TD]1[/TD]
[TD]3[/TD]
[TD]12[/TD]
[TD]2012-08-4[/TD]
[/TR]
[TR]
[TD]2[/TD]
[TD]5[/TD]
[TD]10[/TD]
[TD]2012-08-04[/TD]
[/TR]
[TR]
[TD]3[/TD]
[TD]7[/TD]
[TD]8[/TD]
[TD]2010-04-05[/TD]
[/TR]
[TR]
[TD]4[/TD]
[TD]6[/TD]
[TD]9[/TD]
[TD]2009-06-08[/TD]
[/TR]
[TR]
[TD]5[/TD]
[TD]4[/TD]
[TD]6[/TD]
[TD]2008-05-04[/TD]
[/TR]
[TR]
[TD]6[/TD]
[TD]5[/TD]
[TD]4[/TD]
[TD]2008-05-04[/TD]
[/TR]
[TR]
[TD]7[/TD]
[TD]3[/TD]
[TD]10[/TD]
[TD]2008-05-04[/TD]
[/TR]
[/TABLE]



We will make use of the above data set. Now we need to create Person objects for each row and create an array of these objects for sorting.
Add this code to your main function:

  
Person person1 = new Person {Id = 0, Age = 5, Height = 10, RegisteredDate = new DateTime(2011, 3, 3)};
Person person2 = new Person {Id = 1, Age = 3, Height = 12, RegisteredDate = new DateTime(2012, 8, 4)};
Person person3 = new Person {Id = 2, Age = 5, Height = 10, RegisteredDate = new DateTime(2012, 8, 4)};
Person person4 = new Person {Id = 3, Age = 7, Height = 8, RegisteredDate = new DateTime(2010, 4, 5)};
Person person5 = new Person {Id = 4, Age = 6, Height = 9, RegisteredDate = new DateTime(2009, 6, 8)};
Person person6 = new Person {Id = 5, Age = 4, Height = 6, RegisteredDate = new DateTime(2008, 5, 4)};
Person person7 = new Person {Id = 6, Age = 5, Height = 4, RegisteredDate = new DateTime(2008, 5, 4)};
Person person8 = new Person {Id = 7, Age = 3, Height = 10, RegisteredDate = new DateTime(2008, 5, 4)};
Person[] persons = new Person[] {person1, person2, person3, person4, person5, person6, person7, person8};

Here we create 8 person objects (the data from the above table is just hard-coded). In a real application this data would come from a database or a text file.

Sort by RegisteredDate

The first thing we want to do is sort by registered date in ascending order. To do this we simply use the OrderBy method as follows:

persons = person.OrderBy(k => k.RegisteredDate).ToArray();

The following screenshot shows the output:

Attached File  Date1.jpg   58.6K   135 downloads

Sort by increasing age and decreasing height

First we make use of the order by to sort by age. Then to sort in descending order we chain ThenByDescending to OrderBy like this:

  persons = persons.OrderBy(k => k.Age).ThenByDescending(k=>k.Height). ToArray();

The output of this code is:

Attached File  date2.png   20.24K   138 downloads

Notice when dates are equal that the records are sorted in descending order by height when ages are equal.

Sort by increasing height and increasing RegisteredDate

As the last example, let us sort in increasing order by height and increasing order by RegisteredDate.
Example code:

  persons = persons.OrderBy(k => k.Height).ThenBy(k=>k.RegisteredDate). ToArray();

The output is:

Attached File  date3.jpg   63.49K   128 downloads

Notice that the collection is ordered by height. In the event that height is the same for 2 or more entries those entires are sorted in increasing order by RegisteredDate.

You can make even more complicated sorts by appending more ThenBy clauses after the initial OrderBy clause. Note that in order to use ThenBy and ThenByDescending you must chain the call to an OrderBy or OrderByDescending.

#2
AceInfinity

AceInfinity

    Advanced Member

  • Members
  • PipPipPip
  • 35 posts
This isn't really advanced, with LINQ this is just basic sorting, but it's an alright tutorial. For defining the user-defined types of Person though, even though it's aside from the tutorial itself there are a few better ways of doing that. "var" should be switched to "Person" too as that's what the defined type is a type of.

You're just sorting by class properties though here, otherwise it's essentially the same as sorting an array of integers, or strings, etc...

Microsoft MVP (2012) - My MSDN Profile
~ "The universe is an intelligence test." - Timothy Leary ~


#3
chili5

chili5

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 7,247 posts
  • Programming Language:Java, C#, PHP
  • Learning:C, C++, C#, PHP, Transact-SQL, Assembly, Scheme
I use 'var' because it is quicker to type and in Visual Studio I can easily find the type just by putting my mouse over the variable name. I don't really gain anything from doing Person p = new Person(...).

#4
AceInfinity

AceInfinity

    Advanced Member

  • Members
  • PipPipPip
  • 35 posts

View Postchili5, on 12 April 2012 - 05:46 AM, said:

I use 'var' because it is quicker to type and in Visual Studio I can easily find the type just by putting my mouse over the variable name. I don't really gain anything from doing Person p = new Person(...).

Better habits though...

Microsoft MVP (2012) - My MSDN Profile
~ "The universe is an intelligence test." - Timothy Leary ~


#5
chili5

chili5

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 7,247 posts
  • Programming Language:Java, C#, PHP
  • Learning:C, C++, C#, PHP, Transact-SQL, Assembly, Scheme
Thanks for the feedback. For future tutorials I will not use var. Just to be more clear though, I always use Visual Studio so I don't really gain anything from using the full type. It's only a 'better habit' if I get some benefit from coding with that style.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users