Sign in to follow this  
vegi

[.net] IComparer

Recommended Posts

Hi, i´m using an IComparer to Sort my Pointlist. I want to sort it by increasing x and then increasing y-coordinates But it doesn´t work :(
public class PointComparer : IComparer
    {
        private bool coord;
        //
        public PointComparer(bool coord)
        {
            this.coord = coord;
        }
        //
        int IComparer.Compare(object a, object b)
        {
            var b1 = (Point)a;
            var b2 = (Point)b;
            if(coord)
            {
                if (b1.X < b2.X)
                    return -1;
                if (b1.X > b2.X)
                    return 1;
                return 0;
            }
            else
            {
                if (b1.X == b2.X)
                {
                    if (b1.Y < b2.Y)
                        return -1;
                    if (b1.Y > b2.Y)
                        return 1;
                    return 0;
                }
                return 0;
            }
        }
    }
//...
PVRTXList.Sort(new PointComparer(true)); // to sort by x
PVRTXList.Sort(new PointComparer(false)); // to sort the same x by y

Share this post


Link to post
Share on other sites
You should perhaps try sorting using one comparer, instead of doing it in two steps, which is just awkward.


public class PointComparer : IComparer<Point>
{
public int Compare(Point a, Point b)
{
if ( a.x < b.x ) return -1;
else if ( a.x > b.x ) return 1;
else return a.y - b.y;
}
}



I haven't tested it, but it should work. I you really need a non-generic version, just add the necessary casts. Also, it might be safer to replace the last line by a couple of extra ifs, as you might have some overflow issues there.

Share this post


Link to post
Share on other sites

public class App
{
public static void Main( string[] args )
{
var pts = new List<Point>();

pts.Add( new Point( 1, 1 ) );
pts.Add( new Point( 2, 1 ) );
pts.Add( new Point( 1, 2 ) );
pts.Add( new Point( 2, 2 ) );

pts.Sort( new PointComparer() );

foreach ( var p in pts )
{
Console.WriteLine( p );
}
}
}

public class Point
{
public Point( float x, float y )
{
this.X = x;
this.Y = y;
}

public float X { get; set; }

public float Y { get; set; }

public override string ToString()
{
return string.Format( "({0}, {1})", X, Y );
}
}

public class PointComparer : IComparer<Point>
{
public int Compare( Point a, Point b )
{
var cx = a.X.CompareTo( b.X );

if ( cx != 0 )
{
return cx;
}
else
{
return a.Y.CompareTo( b.Y );
}
}
}


Seems to work:

(1, 1)
(1, 2)
(2, 1)
(2, 2)

Share this post


Link to post
Share on other sites
You're making the assumptions that the second sort knows it has to leave the "same X island" unperturbed, which I think is the case if the algorithm is stable (i.e. the relative position of equal elements must be preserved), but which it is not according to MSDN.

So, the algorithm you use probably just guarantees that a) the resulting list will be a permutation of the original one, and b) the elements will be ordered with respect to the predicate you provided. This means that the list {(1,2), (1,1), (2,2), (2,3), (3,3), (3,1)} can be sorted to many different "valid" lists according to your predicate (426 different possibilities if I'm not mistaken). My version of the predicate only allows for one correct solution.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this