mcs26
asked on
C# Sorting Custom Class
Hi,
I have a class called "TradeHolder" (code below). I have a List<TradeHolder> which I wish to sort. The question I have is sometimes I want sort the List on "MaxWin" (double) other times I will need to sort it on "TradeReturn" (double) other times "PeriodLosing" (int) etc.
Also I may need to sort it ascending or descending. How is the best way to do this using the IComparable interface?
Thanks,
M
I have a class called "TradeHolder" (code below). I have a List<TradeHolder> which I wish to sort. The question I have is sometimes I want sort the List on "MaxWin" (double) other times I will need to sort it on "TradeReturn" (double) other times "PeriodLosing" (int) etc.
Also I may need to sort it ascending or descending. How is the best way to do this using the IComparable interface?
public class TradeHolder : IComparable<TradeHolder>
{
public double TradeReturn, BasePnL, MaxLose, MaxWin;
public int PeriodInTrade, PeriodLosing;
public string ExitReason, LockInLevel;
public Boolean LockInActive;
public enumOutCome Outcome;
public int IComparable.CompareTo(TradeHolder TH)
{
}
}
Thanks,
M
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi Kaufmed,
Thanks for the posts & code. I now understand why you suggest using the IComparer interface.
I'm being quite dumb but I do have a question. As we'r using the IComparer interface we have to implement the Compare method which is fine. However in the Compare method you use the CompareTo method. So does this mean my TradeHolder class has to implement the IComparable interface and then write some code in the CompareTo method?
Thanks,
M
Thanks for the posts & code. I now understand why you suggest using the IComparer interface.
I'm being quite dumb but I do have a question. As we'r using the IComparer interface we have to implement the Compare method which is fine. However in the Compare method you use the CompareTo method. So does this mean my TradeHolder class has to implement the IComparable interface and then write some code in the CompareTo method?
Thanks,
M
public int Compare(TradeHolder x, TradeHolder y)
{
if (this._sortDescending)
{
return y.MaxWin.CompareTo(x.MaxWin);
}
else
{
return x.MaxWin.CompareTo(y.MaxWin);
}
}
It does not. The only reason I used CompareTo was that it functions in exactly the way I needed it to for the comparisons. The Compare method returns an integer. This integer can be the following:
Quite conveniently, this is exactly what CompareTo returns as well. Since items which implement the IComparable interface are guaranteed to have the CompareTo method, and since that method returns exactly the same information that I needed for the Compare method, I just used the CompareTo method.
Now, this is not to imply that it is required. I certainly could have implemented my own logic--so long as it returns the information above. For example:
Here I've used no CompareTo. I just made sure to return each of the values -1, 1, & 0 accordingly. Your logic can be whatever you need it to be. Just ensure that whichever object you want to be less than the other returns -1, whichever you want to be higher than returns 1, and if they are equal return 0.
Here's an example of sorting strings where ones that contain the word "Important" (case-sensitive) go at the beginning--regardless of spelling--and the rest get sorted alphabetically:
...and to make it so Important strings are at the beginning, and everything else is sorted descending:
-1: the left item is less than the right item
0: both items are equal
1: the left item is greater than the right item
0: both items are equal
1: the left item is greater than the right item
Quite conveniently, this is exactly what CompareTo returns as well. Since items which implement the IComparable interface are guaranteed to have the CompareTo method, and since that method returns exactly the same information that I needed for the Compare method, I just used the CompareTo method.
Now, this is not to imply that it is required. I certainly could have implemented my own logic--so long as it returns the information above. For example:
public int Compare(TradeHolder x, TradeHolder y)
{
if (this._sortDescending)
{
if (x.MaxWin < y.MaxWin)
{
return 1;
}
else if (x.MaxWin > y.MaxWin)
{
return -1;
}
else
{
return 0;
}
}
else
{
if (x.MaxWin < y.MaxWin)
{
return -1;
}
else if (x.MaxWin > y.MaxWin)
{
return 1;
}
else
{
return 0;
}
}
}
Here I've used no CompareTo. I just made sure to return each of the values -1, 1, & 0 accordingly. Your logic can be whatever you need it to be. Just ensure that whichever object you want to be less than the other returns -1, whichever you want to be higher than returns 1, and if they are equal return 0.
Here's an example of sorting strings where ones that contain the word "Important" (case-sensitive) go at the beginning--regardless of spelling--and the rest get sorted alphabetically:
using System;
using System.Collections.Generic;
namespace _27999436
{
class Program
{
static void Main(string[] args)
{
List<string> someStrings = new List<string>()
{
"this isn't very important",
"Important - this is important",
"this is just another string",
"a string that is not important",
"Important - make sure this is first",
};
someStrings.Sort(new ImportantComparer());
someStrings.ForEach(Console.WriteLine);
}
}
public class ImportantComparer : IComparer<string>
{
public int Compare(string x, string y)
{
bool xIsImportant = x.Contains("Important");
bool yIsImportant = y.Contains("Important");
if (xIsImportant)
{
if (yIsImportant)
{
return x.CompareTo(y);
}
else
{
return -1;
}
}
else if (yIsImportant)
{
return 1;
}
else
{
return x.CompareTo(y);
}
}
}
}
...and to make it so Important strings are at the beginning, and everything else is sorted descending:
...
else
{
return y.CompareTo(x); // flip x and y
}
}
}
}
ASKER
Thanks again for the clear explanation
Some fun I had recently was implementing a comparer that would be a bit more flexible in not requiring me to have create new classes for every property I wanted to compare. It's a bit more verbose to use, but if you are using .NET 3.0+, then you can do something like:
Open in new window
...and usage would look like:
Open in new window
...where the first type parameter to the PropertyComparer is the type of items in the list (TradeHolder), and the second type parameter is the type of thing being compared (double)--MaxWin and TradeReturn in my examples above.