How does the return value of IComparer.Compare function decide the order of sorting operation? What is the significance of return values in deciding the sorting order? How does the flow of Array.Sort() happen?
For example, :
int[] ii = new int[3] { 8,1,4};
Array.Sort(ii, new myComp1());
Is there any way to understand the flow of the sorting operation. I mean if I want to decide a specific order on sorting, then how should i write if-else conditions or return values?
class myComp1 : IComparer<int>
{
public int Compare(int x, int y)
{
if (x == y)
return 1;
else if (x > y)
return -1;
else
return 0;
}
}
For example in the code given below, I don't get the significance of the return values of comparer function whether it is going to make it ascending order or descending order or some random order. MSDN doesn't explain it very clearly.
Any help.
I would also like to understand: does Array.Sort() in below code compares 8 and 1 first, then 1 and 4, then 1 and 8? Is there any flow to this execution so that as a programmer I can figure it out before writing the actual code? Thanks.
int[] kk = new int[3] { 8,1,4};
Array.Sort(kk, new myComp2());
class myComp2 : IComparer<int>
{
public int Compare(int x, int y)
{
int res = 0;
if (x == y)
return 1;
else if (x > y)
return 2;
else
return 3;
return res;
}
}
Array.Sort
or any other .Sort
variations in .NET sort items in ascending order.
When you implement your comparer, the meaning of the result is very simple:
x
less than y
x
greater than y
x
equals y
The order of comparing items in a set depends on a sorting algorithm, so no specific order of Compare
calls is guaranteed.
Having IComparer<>
is a good abstraction, and can be useful in other scenarios, not for sorting only.
If you want any specific order of items, you can either define your rules of comparer that preserves transitivity or perhaps not using .Sort
.
UPDATE
As a programmer, you should think:
public int Compare(int x, int y)
{
// OPTION 1
if (x < y)
return -1; // X is less than Y, place X before Y - acsending order
...
// OPTION 2
if (x < y)
return 1; // X is less than Y, place X after Y - descending order
...
return 0; // keep order of X and Y if possible (stable comparison only)
}
UPDATE 2
OK, imagine we have a comparer defined like this:
interface IComparer<T>
{
SortPlacement Compare(T x, T y);
}
Where SortPlacement
is defined like this:
enum SortPlacement
{
Try_To_Keep_Same_Order_Of_X_and_Y = 0,
Place_X_Before_Y_Ascending_Order = -1, // or any negative number
Place_X_After_Y_Descending_Order = 1, // or any positive number
}
When you implement you comparer you are super clear:
public SortPlacement Compare(int x, int y)
{
// OPTION 1
if (x < y)
return SortPlacement.Place_X_Before_Y_Ascending_Order;
...
// OPTION 2
if (x < y)
return SortPlacement.Place_X_After_Y_Descending_Order;
...
// OPTION 3
return SortPlacement.Try_To_Keep_Same_Order_Of_X_and_Y;
}
Now forget about silly enumertion type and replace it with integer numbers - that is a simple convention.