sorting

  • Thread starter Thread starter Peter Kirk
  • Start date Start date
P

Peter Kirk

Hi

say I have a list of Person objects, which I want to sort. But I don't just
want to sort by "name" say, but by several fields in the Person object.
Maybe 1st priority by height, 2nd priority by weight, and 3rd priority by
age.

A Person object has many attributes though, and I want to be able to select
between all of the fields for sorting (with 1st, 2nd, 3rd priority).


What would be a good approach?

Thanks,
Peter
 
Peter Kirk said:
say I have a list of Person objects, which I want to sort. But I don't just
want to sort by "name" say, but by several fields in the Person object.
Maybe 1st priority by height, 2nd priority by weight, and 3rd priority by
age.

What would be a good approach?

Write a static method (following the signature of the Comparison<T>
delegate where T is Person) which accepts two Person objects and returns
an integer. The return value should be less than zero if the first
person comes first, equal to zero if the two persons compare equally,
and greater than zero if the second person comes first. When writing the
method, compare the heights first, and only continue to the weight if
the heights are equal, and so on.

Pass this static method to List<T>.Sort().

If you want a fully general solution, you can get it by playing with
reflection, but get the hard-coded solution working first. After that,
it's relatively easy to use reflection to access the values of a given
property on a given object, and write a loop to perform the comparisons
for each property in turn.

-- Barry
 
Peter said:
Hi

say I have a list of Person objects, which I want to sort. But I don't just
want to sort by "name" say, but by several fields in the Person object.
Maybe 1st priority by height, 2nd priority by weight, and 3rd priority by
age.

A Person object has many attributes though, and I want to be able to select
between all of the fields for sorting (with 1st, 2nd, 3rd priority).


What would be a good approach?

Most ways of sorting have an overload that accepts an IComparer object
(*), which gets asked to compare pairs of objects and return the order
they should sort in. You could define a PersonComparer class that
implements IComparer - give this class a property or properties that
tell it how to sort Persons, then when you want to sort, create an
appropriate PersonComparer and give it to the sort method.

* eg
<http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemArrayClassSortTopic3.asp>
= <http://tinyurl.com/odry5>
 
one trick is to string together the string properties, and sort on them.



I'm writing this mostly from memory, so hopefully its nearly all correct.
but you should see the idea.

( case LastNameAndFirstName is what I'm talking about).


At the least, you'll see how to write 1 comparer for multiple properites ..
using the Enum thing.

...


using System;
using System.Collections;


namespace MyApplication.Comparers
{


internal sealed class EmployeeComparer : IComparer
{
private EmployeeSortColumns m_sortValue = EmployeeSortColumns.None ;

public enum EmployeeSortColumns
{
None = 0 , LastName = 1 , FirstName = 2 , LastNameAndFirstName = 3
}

public EmployeeComparer(EmployeeSortColumns sortValue)
{
m_sortValue = sortValue;
}

public int Compare(object x,object y)
{
switch(m_sortValue)
{

case EmployeeSortColumns.None :
return 0;


case EmployeeSortColumns.FirstName :

return ((Employee)x).FirstName .CompareTo(((Employee )y).FirstName );
//break;
case EmployeeSortColumns.LastName :


return ((Employee)x).LastName.CompareTo(((Employee )y).LastName );

case LastNameAndFirstName :

string xValue = ((Employee)x).LastName + ((Employee)x).FirstName;
string yValue = ((Employee)y).LastName + ((Employee)y).FirstName;

return xValue.CompareTo(yValue);



default:
return ((Employee)x).LastName .CompareTo(((Employee )y).LastName );
// break;
}
}
}


}






...

Other comments:

While I'm usually in favor of using strong objects and collections, this is
one area where the strongly typed dataset is helpful, since
it has a .Select ( filter, sortby ) method.

MyStrongDS.EmpTable.Select ("" , "LastName , FirstName DESC , City");

something like that.
 
sloan said:
one trick is to string together the string properties, and sort on them.

Be careful when using this method. Some data types will not be sorted
correctly. One example off the top of my head is DateTime.

Brian
 
Yeah, I concur.

I think maybe that's why sometimes I switch out to the StronglyTyped
DataSets...
When I need advanced sorting features.....

And I dont' have in production any of these "string togethers", except maybe
one LastName/First thing.

But the option exists........ for certain situations.

Thanks for voicing the "gotcha" on that method.
 
Yeah, just recently I used that method as a quick get-r-done
implementation and marked the code with a TODO comment to remind me to
go back in and change it. Well, I forgot to change it and I missed the
problem during testing because the incorrect order only occurred in
less than 1% of the scenarios. I was really frustrated with myself for
not doing it right the first time.

Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top