50

我正在尝试使用IComparer对点列表进行排序。这是 IComparer 类:

public class CoordinatesBasedComparer : IComparer
{
    public int Compare(Object q, Object r)
    {
        Point a = (p)q;
        Point b = (p)r;
        if ((a.x == b.x) && (a.y == b.y))
            return 0;
        if ((a.x < b.x) || ((a.x == b.x) && (a.y < b.y)))
            return -1;

        return 1;
    }
}

在客户端代码中,我正在尝试使用此类对点列表 p (类型List<Point>)进行排序:

CoordinatesBasedComparer c = new CoordinatesBasedComparer();
Points.Sort(c);

代码出错了。显然,它期望IComparer<Point>作为排序方法的参数。
我需要做什么来解决这个问题?

4

4 回答 4

62

您需要实现强类型接口 ( MSDN )。

public class CoordinatesBasedComparer : IComparer<Point>
{
    public int Compare(Point a, Point b)
    {
        if ((a.x == b.x) && (a.y == b.y))
            return 0;
        if ((a.x < b.x) || ((a.x == b.x) && (a.y < b.y)))
            return -1;

        return 1;
    }
}

顺便说一句,我认为您使用了太多大括号,我认为只有在它们对编译器有贡献时才应该使用它们。这是我的版本:

if (a.x == b.x && a.y == b.y)
    return 0;
if (a.x < b.x || (a.x == b.x && a.y < b.y))
    return -1;

就像我不喜欢人们使用return (0).


请注意,如果您以 .Net-3.5+ 应用程序为目标,则可以使用 LINQ,它在排序方面更容易甚至更快。

LINQ 版本可以类似于:

var orderedList = Points.OrderBy(point => point.x)
                        .ThenBy(point => point.y)
                        .ToList();
于 2013-01-15T11:11:00.813 回答
13
public class CoordinatesBasedComparer : IComparer, IComparer<Point>
{
    public int Compare(Point a, Point b)
    {
        if ((a.x == b.x) && (a.y == b.y))
            return 0;
        if ((a.x < b.x) || ((a.x == b.x) && (a.y < b.y)))
            return -1;

        return 1;
    }
    int IComparer.Compare(Object q, Object r)
    {
        return Compare((Point)q, (Point)r);            
    }
}
于 2013-01-15T11:11:36.273 回答
10

如果你像我一样慢,在使用IComparer. 考虑它的方法是什么时候x应该先去,返回-1。什么时候y应该先去,返回1。

如果您有很多字段要排序,它仍然会让人感到困惑。您可以使用 anEnum使您的比较逻辑比 1 和 -1 更具可读性,然后转换结果。

此示例将具有最少空字段的对象放在前面。

public class NullishObjectsToTheBackOfTheLine: IComparer<ClassToCompare>
{
    private enum Xy
    {
        X = -1,
        Both = 0,
        Y = 1
    };

    //the IComparer implementation wraps your readable code in an int cast.
    public int Compare(ClassToCompare x, ClassToCompare y)
    {
        return (int) CompareXy(x, y);
    }

    private static Xy CompareXy(ClassToCompare x, ClassToCompare y)
    {
        if (x == null && y == null) return Xy.Both;

        //put any nulls at the end of the list
        if (x == null) return Xy.Y;
        if (y == null) return Xy.X;

        if (x.Country == y.Country && x.ProductId == y.ProductId) return Xy.Both;

        //put the least amount of at the front
        if (x.ProductId == null && x.Country == null) return Xy.Y;
        if (y.ProductId == null && y.Country == null) return Xy.X;

        //put the country values that are not nulls in front
        if (x.Country != y.Country) return x.Country != null ? Xy.X :  Xy.Y;

        //if we got this far, one of these has a null product id and the other doesn't
        return x.ProductId != null ? Xy.X : Xy.Y;
    }

}

public class ClassToCompare
{
    public string Country { get; set; }
    public string ProductId { get; set; }
}
于 2017-07-19T22:03:09.660 回答
0

InvalidOperation将类型对象添加MyClassSortedList<MyClass>. 我错误地实现了 IComparer 接口。我需要实现的是 IComparable 与方法 CompareTo(MyClass other),而不是 ICompare.Compare(MyClass x, MyClass y)。这是一个简化的例子:

SortedList<MyClass> sortedList = new SortedList<MyClass>();
MyClass a=new MyClass(), b=new MyClass();
sortedList.Add(a);
sortedList.Add(b); // Note, sort only happens once second element is added

这修复了它

public class MyClass : IComparable<MyClass>
{
    int IComparable<MyClass>.CompareTo(MyClass other)
    {
        // DoCompareFunction(this, other); and return -1,0,1
    }
}

这被打破了(如果添加到 ,请不要这样做SortedList<MyClass>

public class MyClass : IComparer<MyClass>
{
    int IComparable<MyClass>.Compare(MyClass x, MyClass y)
    {
        // DoCompareFunction(x, y); and return -1,0,1
    }
}

这是错误:

无法比较数组中的两个元素。
在 System.Collections.Generic.ArraySortHelper`1.BinarySearch(T[] 数组,Int32 索引,Int32 长度,T 值,IComparer`1 比较器)
在 System.Array.BinarySearch[T](T[] 数组,Int32 索引, Int32 长度,T 值,IComparer`1 比较器)
在 System.Collections.Generic.SortedList`2.Add(TKey 键,TValue 值)

于 2017-06-10T12:09:50.433 回答