ArrayList.Sort

1 view
Skip to first unread message

cipri

unread,
Jun 6, 2003, 12:06:53 PM6/6/03
to
I have looked up other posts regarding this subject. They
haven't helped.

Each item of my ArrayList consists of an object type.
I am comparing one value in the object type.

So say my datatype is houseDat.
houseDat consists of house.Length
house.Height
house.Color
house.cubic_feet

so each element in ArrayList is of type houseDat.

When I do...

ArrayList myHouse = new ArrayList()
...then add houseDat objects.

I want to do myHouse.Sort()//or whatever needs to go in
the ()
and get the items in myHouse
sorted in descending order by the house.cubic_feet value.

I believe I am supposed to use the IComparer interface.
But what am I comparing? ArrayList items or houseDat
objects? And if I am comparing them within the same
arraylist then what am I really comparing since the
list goes from i=0 to i=n (myHouse[i], myHouse[i+1],
myHouse[i+2]...myHouse[i+n])?

How do I set up the IComparer class? Or am I supposed to
use something else? If using I comparer, am I supposed to
use Compare(object a, object b) or CompareTo(object c)?
Are objects my arraylist items or my data type?

Yes, I realize this is trivial.

Thanks in Advance for any Help.

Rajasi Saha

unread,
Jun 6, 2003, 1:45:22 PM6/6/03
to
Here is an example. I have an ArrayList of DocNode objects and when i do
ArrayList.Sort, i really want to sort on the field m_dTermWeight of DocNode.
DocNode overrides CompareTo, so that during the Sort process, whenever one
DocNode is compared to another, it really compares the m_dTermWeight of one
DocNode to that of another.
Hope this makes it clearer.
rajasi
---------------

class DocNode : IComparable
{
public decimal m_dTermWeight;
public long m_lDocId;

public DocNode(decimal dTermWeight, long lDocId)
{
m_dTermWeight = dTermWeight;
m_lDocId = lDocId;
}

// sorting on DocNode means sorting on m_dTermWeight
public Int32 CompareTo(Object value)
{
if (value is DocNode) // sanity check - object being compared should be
DocNode
{
DocNode node = (DocNode)value;
return this.m_dTermWeight.CompareTo(node.m_dTermWeight);
}
else return -1;
}
}


"cipri" <Irene.C...@RCCorp.net> wrote in message
news:080101c32c45$a52a6350$a001...@phx.gbl...

Ignacio Machin

unread,
Jun 6, 2003, 2:11:48 PM6/6/03
to
Hi Irene,

The sorting is not an easy matter, I tried to do something very general
using reflection and as today I have used it in three different projects
with 100% success.
I will show you the logic of the code and I attach the full code below

I had several times the needs to sort collections of objets, I could not
force those objects to implement the IComparable interface as it would be
cumbersome, so what I did was create my own IComparer implementation and
using reflection get the property that I needed to sort by, this has a
couple of drawback:
1- The property's type used to sort has to implement IComparable
2- You can only sort using one property of the type of the objects being
compared.

I had no problem with these restrictions and as far as today I'm very happy
with the solution.

I will show you how to use the class with your own type.

I have an ArrayList of House and I want to order it by let's say Cubit_Feet
property:

//******************************* USING THE SORTER CLASS
********************************
ArrayList sortedlist = houseList.Clone() // I will clone the original
ArrayList to keep the original

// Here I define the new sorter class , it takes two parameters the name of
the property and if it's ascending or descending.
ClassSorter sorter = new ClassSorter( "Cubit_Feet" ,
SortDirection.Ascending );

//Call the Sort method
sortedlist.Sort( sorter );

//**************************************************************************
******************

and voila, that's all what you have to do to use the class :) piece of cake
, right?

now the code of the class ClassSorter:
//********************************************** FULL CODE OF THE SORTER
CLASS *******************
// The class implement the IComparer interface, this interface define oe
method Compare( object, object )
public class ClassSorter: IComparer
{
protected string sortBy; // This attribute
keep the name of the property used to compare
protected SortDirection sortDirection; // The direction of the sort
( Ascending or Descending )


#region Constructors
//Nothign especial here, just assign the members.
public ClassSorter(string sortBy, SortDirection
sortDirection)
{
this.sortBy = sortBy;
this.sortDirection = sortDirection;
}
#endregion


#region IComparer implementation
// This is the method that IComparer define, as you can see the real logic
is in a method the class define.
public int Compare(object x, object y)
{
return Compare( x, y, sortBy);

}
#endregion

#region Compare logic
/*
The real implementation.
The method itself is VERY simple all it does is get the value of the
property casted to IComparable and simply compare them. we do this using
reflection:
icy = (IComparable)y.GetType().GetProperty( comparer).GetValue(y, null);
and then depending of the sorting order passed in the constructor return
the correct value
If the type of the property is string we set both value to the same case,
this would be needed to be change if you want a case sensitive comparision,
or passed in the constructor as a parameter.

A tricky part is when Idetect that a "." is present in the property name,
this is an indication that the property is a complex type and what I do is
call the function recursively , I get the property's value using the the
same code, and pass as parameter the name of the inner property.
this allow me to do this:
ClassSorter( "Property.Property" , ... )

*/
int Compare( object x, object y, string comparer)
{
if ( comparer.IndexOf( ".") != -1 )
{
//split the string
string[] parts = comparer.Split( new char[]{ '.'} );
return Compare( x.GetType().GetProperty( parts[0]).GetValue(x, null) ,
y.GetType().GetProperty( parts[0]).GetValue(y, null) , parts[1]
);
}
else
{
IComparable icx, icy;
icx =
(IComparable)x.GetType().GetProperty( comparer).GetValue(x, null);
icy =
(IComparable)y.GetType().GetProperty( comparer).GetValue(y, null);

if ( x.GetType().GetProperty(comparer).PropertyType ==
typeof(System.String) )
{
icx = (IComparable) icx.ToString().ToUpper();
icy = (IComparable) icy.ToString().ToUpper();
}

if(this.sortDirection == SortDirection.Descending)
return icy.CompareTo(icx);
else
return icx.CompareTo(icy);
}

}

#endregion

} // End of the class
public enum SortDirection
{
Ascending = 0,
Descending = 1
}
//********************************************* END SORTER CLASS CODE
*************************


I'm 100% sure that this class solve your problem as well as futures sorting
problems. Now an extension I included recently but did not show you here is
allow the use of method as well as properties this is very easy all you have
to do is substitute GetProperty.GetValue by GetMethod.Invoke()

Hope this help,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation


"cipri" <Irene.C...@RCCorp.net> wrote in message
news:080101c32c45$a52a6350$a001...@phx.gbl...

cipri

unread,
Jun 6, 2003, 3:39:49 PM6/6/03
to
Rajasi,

I was able to get this working for the IComparable,
but I thougth ArrayList used ICompare, exclusively. Do I
need to use ICompare in conjuntion with IComparable?

Also, the Sort prototypes for ArrayList only have
ICompare as an option.

Am missing somthing?

Thanks for your reply.
Irene

>.
>

Gang Peng[MSFT]

unread,
Jun 11, 2003, 7:07:03 PM6/11/03
to

>but I thougth ArrayList used ICompare, exclusively. Do I
>need to use ICompare in conjuntion with IComparable?
>
If you don't specify "comparer" argument while calling ArrayList.Sort, the
default comparer will be used.
When Sort is trying to compare two objects, it will call following method
on the comparer.
public int Compare(Object a, Object b) ;

This function in the default comparer is implemented as following:
Cast a to IComparable, if succeeded, call CompareTo on the interface.
Cast b to IComparable, if succeeded, call CompareTo on the interface.
If neither if the casts succeeded, throw an exception.

Hope this helps.

Gang Peng
CLR
Microsoft

Reply all
Reply to author
Forward
0 new messages