logo

Custom Sorting With IComparable and IComparer

By Sadhana G
Printer Friendly Version
View My Articles
2242 Views
    

Sometimes, you want to be able to sort objects on a number of different fields. For example, employees can be sorted by their name, years of service, pay rate; or blog posts by the date they were posted, their status, number of comments, the author. It's really easy to offer all these sorting methods. Best of all you don't have to write too much code.


Default Sorting

Suppose we have a Politician class:


public class Politician
{
private string ssn;
private string name;
private int powerIndex;
private int voterBaseIndex;
private int suckitudeIndex;

public string SSN
{
get { return this.ssn; }
}

public string Name
{
get { return this.name; }
}

public int PowerIndex
{
get { return this.powerIndex; }
}

public int VoterBaseIndex
{
get { return this.voterBaseIndex; }
}

public int SuckitudeIndex
{
get { return this.suckitudeIndex; }
}
}

We want to allow the users to sort by name, powerIndex, voterBaseIndex, or the suckitudeIndex. We feel that people generally want to sort the politicians by their suckitudeIndex. So we're going to have the default sorting method sort by the suckitudeIndex while giving users the option of sorting by various other indices, too.

Default Sorting: IComparable

To tell .NET how to sort objects by default, all we need to do is inherit from the IComparable interface:

public class Politician : System.IComparable<Politician>

You notice that we're using the generic interface, which takes in an object of the type we're interested in, instead of the normal IComparable interface, which takes in whatever object.

The IComparable interface has a single method that we need to implement: CompareTo; the implementation is straight-forward:


public int CompareTo(Politician politician)
{
// NULL is considered to be smaller than
// any other value.
if (politician == null)
{
return 1;
}

else if (this.suckitudeIndex < politician.suckitudeIndex)
{
return -1;
}

else if (this.suckitudeIndex == politician.suckitudeIndex)
{
return 0;
}

else { return 1;
}
}

Sorting by Power Index: IComparer

A class can sort by any number of fields or any combination of fields. We do this by creating classes that implement the IComparer.

For example:


public class PowerIndexComparer : System.Collections.Generic.IComparer<Politician>
{
public int Compare(Politician first, Politician second)
{
if (first == null & second == null)
{
return 0;
}

else if (first == null)
{
return -1;
}

else if (second == null)
{
return 1;
}

else if (first.powerIndex < second.powerIndex)
{
return -1;
}

else if (first.powerIndex == second.powerIndex)
{
return 0;
}

else { return 1;
}
}
}

And when you want to sort politicians by the power index, simply pass along the IComparable object to the sort method:

politicians.Sort(new PowerIndexComparer());

Usually, I create the IComparable classes as private classes within the main class. For example, the PowerIndexComparer would be declared as a private class within the Politician class. This was how I saw it done in one of the books I read. It makes sense, because all comparer classes aren't independent/full-fledged classes but rather part of the Politician class. So the way this would work:


public class Politician : System.IComparable<Politician>
{
private class PowerIndexComparer : System.Collections.Generic.IComparer<Politician>

{
public int Compare(Politician first, Politician second)
{
if (first == null & second == null)
{
return 0;
}

else if (first == null)
{
return -1;
}

else if (second == null)
{
return 1;
}

else if (first.powerIndex < second.powerIndex)
{
return -1;
}

else if (first.powerIndex == second.powerIndex)
{
return 0;
}

else { return 1;
}
}
}

public static System.Collections.Generic.IComparer<Politician> PowerIndexSorter
{
get { return new PowerIndexComparer(); }
}
}

So when you want to sort by power index:

politicians.Sort(Politician.PowerIndexSorter);
Original article here



Didn't Find The Answer You Were Looking For?

EggHeadCafe has experts online right now that may know the answer to your question.  We pay them a bonus for answering as many questions as they can.  So, why not help them and yourself by becoming a member (free) and ask them your question right now?
Ask Question In Live Forum

If you have an OpenID and do not want to become a member of the EggHeadCafe forum, you can also sign on to Chat Chaos and post your question to our real time Silverlight chat application.
Ask Question In Chat Chaos

Article Discussion: Custom Sorting With IComparable and IComparer
Sadhana G posted at Wednesday, October 18, 2006 10:12 AM
Original Article
 

Compare or CompareTo
Falaque The DangerDev replied to Sadhana G at Tuesday, February 10, 2009 1:44 AM
Hi,
 I think IComparable have only one method that is CompareTo. Above given example will not work.
 
 modified code:
 
 CompareTo(Politician other)
 {
    Politician first=this;
    Politician second=othere;
    
    //your code
 }
 






  $1000 Contest    [)ia6l0 iii - $231  |  Jonathan VH - $153  |  Huggy Bear - $133  |  egg egg - $100  |  F Cali - $93  |  more Advertise  |  Privacy  |   (c) 2010