CodeThings

Things i discover during my everyday life of trying build some decent code.

I have my own consulting company, Eqa, in which a assist companies in developing web applications based on various microsoft.net technologies.

Tuesday, August 28, 2007

Sorting a List<> object using different sort criterias

I have often had a list of objects that i need to sort. This can easyly be done through a SortedList, but this will only sort on the provided key. I would like to descide if i want to sort by my object.Property1 or object.Property2, ascending or descending etc. Also the SortedList give me problems if i have multiple objects with the same sort-ordinal.

The List<> type has a method, List<>.Sort(...) that can help out on this. In the example below, I have implemented a Person class, a PersonCollection : List and a PersonComparer : IComparer class. The PersonComparer has a constructor that takes a sortorder and a sortdirection as parameters. Calling the mypersonlist.Sort(...) method takes this PersonComparer object and carries out the actual sorting:




using System;
using System.Collections.Generic;
using System.Text;
namespace SortingExample
{
class Program
{
static void Main(string[] args)
{
// Create a friendscollection
PersonCollection friends = new PersonCollection();
friends.Add(new Person("Kaj", 32));
friends.Add(new Person("Frank", 33));
friends.Add(new Person("Morten", 42));
Console.WriteLine("Age, Asc");
// Sort by age asc
PersonComparer sorter = new PersonComparer(PersonSort.Age, SortDirection.Ascending);
friends.Sort(sorter);
PrintNames(friends);
Console.WriteLine("Age, Desc");
// Sort by age desc
sorter.SortDirection = SortDirection.Descending;
friends.Sort(sorter);
PrintNames(friends);
Console.WriteLine("Name, Asc");
// Sort by name asc
sorter.SortDirection = SortDirection.Ascending;
sorter.Sort = PersonSort.Name;
friends.Sort(sorter);
PrintNames(friends);
Console.WriteLine("Name, Desc");
// Sort by name desc
sorter.SortDirection = SortDirection.Descending;
friends.Sort(sorter);
PrintNames(friends);
}

///
/// Printing out the persons of a PersonCollection
///

/// A list of persons.
public static void PrintNames(PersonCollection persons)
{
foreach (Person friend in persons)
{
Console.WriteLine(string.Format("{0} - {1} years", friend.Name, friend.Age));
}
}
}


///
/// The personobject will hold info about a person.
///

public class Person
{
private string _name;
private int _age;

///
/// The name of the person.
///

public string Name
{
get { return _name; }
set { _name = value; }
}

///
/// The age of the person.
///

public int Age
{
get { return _age; }
set { _age = value; }
}

///
/// Initialize the person object with a name and an age.
///

/// The name of the person.
/// The age of the person.
public Person(string name, int age)
{
Name = name;
Age = age;
}
}

///
/// A list of persons...
///

public class PersonCollection : List
{
}

///
/// The different sort orders
///

public enum PersonSort
{
Name,
Age
}

///
/// Sort direction
///

/// The emum values are used for multiplying on a compare result.
/// This makes descending sorts appear in reverse order.
///

public enum SortDirection
{
Ascending = 1,
Descending = -1
}

///
/// This class takes care of comparing two persons. The
/// class uses sorting and sort direction to determine which
/// of the two objects has the highest value.
///

public class PersonComparer : IComparer
{
private PersonSort _sort;
private SortDirection _sortDirection;
public PersonSort Sort
{
get { return this._sort; }
set { this._sort = value; }
}
public SortDirection SortDirection
{
get { return this._sortDirection; }
set { this._sortDirection = value; }
}

public PersonComparer(PersonSort sort, SortDirection direction)
{
this._sort = sort;
this._sortDirection = direction;
}
#region IComparer Members
public int Compare(Person x, Person y)
{
if (_sort == PersonSort.Age)
{
return x.Age.CompareTo(y.Age)*(int)_sortDirection;
}
else
{
return x.Name.CompareTo(y.Name)*(int)_sortDirection;
}
}
#endregion
}
}



1 comments:

Lasse Rasch said...

Great snippet... I have been using an array to do sorting of my objects until now.

But this is much more simpel! Thnx...

Your code has one error though. IComparer must take a object type, so this must be changed for it to compile:

This blogger site will not let me use < or > in my comment, so i have replaced them with [ ]. This must of couse be changed back :-)



1. public class PersonCollection : List

must be changed to :
public class PersonCollection : List[Person]

2. public class PersonComparer : IComparer

must be changed to :
public class PersonComparer : IComparer[Person]


:-)
/Lasse Rasch, R-Coding.