How to sort this array

  • Thread starter Thread starter Arjen
  • Start date Start date
A

Arjen

Hello,

Persons is a hashtable which I convert to an array.

Person[] aPerson = new Person[Persons.Count];
Persons.Values.CopyTo( aPerson, 0 );

Now I can access the person items like aPerson[3].name or
aPerson[3].birthdate.

How can I sort all the array items based on the birthdate?
So that the first name with the birthdate can be found here aPerson[0].name
and aPerson[0].birthdate.

Thanks!
 
Arjen said:
Persons is a hashtable which I convert to an array.

Person[] aPerson = new Person[Persons.Count];
Persons.Values.CopyTo( aPerson, 0 );

Now I can access the person items like aPerson[3].name or
aPerson[3].birthdate.

How can I sort all the array items based on the birthdate?
So that the first name with the birthdate can be found here aPerson[0].name
and aPerson[0].birthdate.

Use Array.Sort with an IComparer which is able to compare instances of
Person by birth date.
 
Okay, that for your answer.
But I don't get it to work.

I also found a document how to sort a hashtable...
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp01212002.asp
But I don't know how to work with it.

Can you give me a little sample code?

Thanks!



Jon Skeet said:
Arjen said:
Persons is a hashtable which I convert to an array.

Person[] aPerson = new Person[Persons.Count];
Persons.Values.CopyTo( aPerson, 0 );

Now I can access the person items like aPerson[3].name or
aPerson[3].birthdate.

How can I sort all the array items based on the birthdate?
So that the first name with the birthdate can be found here aPerson[0].name
and aPerson[0].birthdate.

Use Array.Sort with an IComparer which is able to compare instances of
Person by birth date.
 
This: Okay, that for your answer.
Must be: ...thanks...

What I don't get is...
The hashtable has object... how can I sort the hashtable based on one object
item?

Thanks!
Arjen




Arjen said:
Okay, that for your answer.
But I don't get it to work.

I also found a document how to sort a hashtable...
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp01212002.asp
But I don't know how to work with it.

Can you give me a little sample code?

Thanks!



Jon Skeet said:
Arjen said:
Persons is a hashtable which I convert to an array.

Person[] aPerson = new Person[Persons.Count];
Persons.Values.CopyTo( aPerson, 0 );

Now I can access the person items like aPerson[3].name or
aPerson[3].birthdate.

How can I sort all the array items based on the birthdate?
So that the first name with the birthdate can be found here aPerson[0].name
and aPerson[0].birthdate.

Use Array.Sort with an IComparer which is able to compare instances of
Person by birth date.
 
Arjen said:
This: Okay, that for your answer.
Must be: ...thanks...

What I don't get is...
The hashtable has object... how can I sort the hashtable based
on one object item?

You said before that you didn't want to sort your hashtable - you
wanted to sort an array you'd copied from the hashtable. Sorting a
hashtable doesn't make any sense, as hashtables aren't really ordered.

So, when you've copied your hashtable contents to an array (eg
myPersonArray) you'd then call

Array.Sort (myPersonArray, new BirthDateComparer());

where BirthDateComparer would be a class which implements IComparer by
casting each of the arguments of CompareTo to a Person, then comparing
their birth dates.
 
Hi,
where BirthDateComparer would be a class which implements IComparer by
casting each of the arguments of CompareTo to a Person, then comparing
their birth dates.

Can you show me how this looks like?

Thanks!
 
Arjen said:
Can you show me how this looks like?

It would be *something* like:

public class BirthDateComparer : IComparer
{
public void Compare(object o1, object o2)
{
Person p1 = (Person) o1;
Person p2 = (Person) o2;

DateTime d1 = p1.BirthDate;
DateTime d2 = p2.BirthDate;

return DateTime.Compare (d1, d2);
}
}

(But I haven't compiled and tested the above.)
 
Hi,

Thanks!
With a little change...
public class BirthDateComparer : IComparer
{
public void Compare(object o1, object o2)
{
Person p1 = (Person) o1;
Person p2 = (Person) o2;

DateTime d1 = p1.BirthDate;
DateTime d2 = p2.BirthDate;

return DateTime.Compare (d1, d2);
}
}

Void must be an int because DateTime.Compare returns an int.

Arjen
 
Hi,

I did this class a time ago to sort any IList, it can be used to sort any
class without any requeriment of the class itself, I use reflection to get
the value of the property passed to the constructor and the only thing that
you need to assure is that the Property type you are sorting on implement
IComparable

This is how you use it:

//Create the IComparer
ClassSorter sorter = new ClassSorter( "BirthDate", SortByType.Property,
SortDirection.Ascending);
//This sort the list using the IComparer sorter
passengerList.Sort( sorter);


Here is the code, it's extremely simple, all you need to especify is the
name of the property you will sort by, a note is is that it can be a complex
object and you can go deeper like :
ClassSorter sorter = new ClassSorter( "Spouse.BirthDate",
SortByType.Property, SortDirection.Ascending);

There you are sorting a list of Passenger, by using the Property BirthDate
of the property Spouse ( I hope you followed me :) )

The class implementation is very simple, it basically consist of two
methods, the required IComparer.Compare method:
public int Compare(object x, object y)
{
return Compare( x, y, sortBy);
}

And the "real" Compare method, that using reflection get the value of the
property named on the constructor and compare both:

int Compare( object x, object y, string comparer)
{
//First see if the comparer is a complex expression, if so go recursive
until get the final simple type
if ( comparer.IndexOf( ".") != -1 )
{
//split the string
string[] parts = comparer.Split( new char[]{ '.'} );
// Call recursively
// NOTE:
// I do remember from my Programming class that a Tail recursion can be
implemented iteratively, but it will performed on the next adventure :)
return Compare( x.GetType().GetProperty( parts[0]).GetValue(x, null) ,
y.GetType().GetProperty( parts[0]).GetValue(y, null) , parts[1]
);
}
else
{
IComparable icx, icy;
//Get the value of both property
icx =
(IComparable)x.GetType().GetProperty( comparer).GetValue(x, null);
icy =
(IComparable)y.GetType().GetProperty( comparer).GetValue(y, null);

//Hack, if it's a string do a case insensitive comparision
if ( x.GetType().GetProperty(comparer).PropertyType ==
typeof(System.String) )
{
icx = (IComparable) icx.ToString().ToUpper();
icy = (IComparable) icy.ToString().ToUpper();
}

// See if descending or ascending
if(this.sortDirection == SortDirection.Descending)
return icy.CompareTo(icx);
else
return icx.CompareTo(icy);
}

}


As you can see it's a pretty simple class, but it does solve a big problem.
here is the code in full, if you have any comment just send me an email


Cheers,

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

////////////////********************************* CODE START
****************////////////////
public enum SortByType
{
Method = 0,
Property = 1
}

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

/// <summary>
/// Summary description for ClassSorter.
/// </summary>
public class ClassSorter: IComparer
{
protected string sortBy;
protected SortByType sortByType;
protected SortDirection sortDirection;


#region Constructors
public ClassSorter(string sortBy, SortByType sortByType, SortDirection
sortDirection)
{
this.sortBy = sortBy;
this.sortByType = sortByType;
this.sortDirection = sortDirection;
}
#endregion

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);
}

}

public int Compare(object x, object y)
{
return Compare( x, y, sortBy);
}

}

////////////////********************************* CODE END
****************////////////////
 
Back
Top