Sorting Custom Collections

Sorting custom collections gets a little cumbersome.  In the past I have create a custom collection by subclassing ArrayList and then adding custom classes that implement IComparer.  This works ok if you can pre-define all the different ways you want to sort a collection.  I wanted to be able to sort custom collections on the fly in code by one or more columns in ascending or descending order. 

Basically, you create an ArrayList of your custom objects, then use the ZenComparer class listed below, pass in the Propery names that you would like sorted by and viola! ex.

ex.  Lets say you have a Person class with two properties FirstName and Age.  You add a bunch of these objects to an ArrayList.  Then you want to sort them by First Name:

al.Sort( new ZenComparer(typeof(Person), "FirstName") );

al.Sort( new ZenComparer(typeof(Person), "Age DESC") );

al.Sort( new ZenComparer(typeof(Person), "FirstName", "Age") );

Those three examples will sort the ArrayList by FirstName, then Age Descending, then FirstName and Age.

For the ZenComparer to work, the ArrayList must be homogeneous, i.e. only contain one type of object.  The object you are sorting must have the Properties you specify, Properties are case-sensitive! The Properties you specify must implement IComparer, as long as you are using value types as properties i.e. int, string, bool, DateTime, you should be alright.  You can specify as many search parameters as you want, and also an optional DESC for a descending sort on each Property.

Enjoy:

using System;

 

namespace Development

{

  public class ZenComparer : System.Collections.IComparer

  {

    private Type _objectType;

    private int[] _sortDir;

    private System.Reflection.PropertyInfo[] _pi;

 

    private static System.Collections.Comparer _comparer = System.Collections.Comparer.Default;

    private static readonly string DESCENDING = " DESC";

    private static readonly string ASCENDING = " ASC";

 

    public ZenComparer( Type t, params string[] PropertyNames)

    {

      _objectType = t;

      _pi = new System.Reflection.PropertyInfo[ PropertyNames.Length ];

      _sortDir = new int[ PropertyNames.Length ];

 

      for( int i=0; i<PropertyNames.Length; i++ )

      {

        string s = PropertyNames[i];

        string prop = string.Empty;

        if( s.ToUpper().EndsWith( DESCENDING ) )

        {

          _sortDir[i] = 1;

          prop = s.Substring( 0, s.Length-DESCENDING.Length);

        }

        else if( s.ToUpper().EndsWith( ASCENDING ) )

        {

          _sortDir[i] = -1;

          prop = s.Substring( 0, s.Length-ASCENDING.Length );

        }

        else

        {

          _sortDir[i] = -1;

          prop = s;

        }

 

        _pi[i] = _objectType.GetProperty( prop );

      }

    }

 

    #region IComparer Members

 

    public int Compare(object x, object y)

    {

      int result = 0;

      int i=0;

 

      while( result == 0 && i<_pi.Length )

      {

        object vX = _pi[i].GetValue( y, null );

        object vY = _pi[i].GetValue( x, null );

        result = _comparer.Compare( vX, vY );

        result *= _sortDir[i];

        i++;

      }

 

      return result;

    }

 

    #endregion

  }

}

posted @ Monday, January 31, 2005 9:07 AM


Print

Comments on this entry:

# re: Sorting Custom Collections

Left by Ajit Sanghera at 4/10/2008 12:20 PM

This was great code

Your comment:



 (will not be displayed)


 
 
 
Please add 3 and 5 and type the answer here:
 

Live Comment Preview:

 
«July»
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789