使用IComparer进行排序
我正在尝试使用IComparer
来对点列表进行排序。 这是IComparer类:
public class CoordinatesBasedComparer : IComparer { public int Compare(Object q, Object r) { Point a = (p)q; Point b = (p)r; if ((ax == bx) && (ay == by)) return 0; if ((ax < bx) || ((ax == bx) && (ay < by))) return -1; return 1; } }
在客户端代码中,我试图使用此类来排序点列表p( List
类型):
CoordinatesBasedComparer c = new CoordinatesBasedComparer(); Points.Sort(c);
代码出错了。 显然它期望IComparer
作为sort方法的参数。
我需要做些什么来解决这个问题?
您需要实现强类型接口( MSDN )。
public class CoordinatesBasedComparer : IComparer { public int Compare(Point a, Point b) { if ((ax == bx) && (ay == by)) return 0; if ((ax < bx) || ((ax == bx) && (ay < by))) return -1; return 1; } }
顺便说一句,我认为你使用了太多的括号,我相信只有当他们为编译器做出贡献时才应该使用它们。 这是我的版本:
if (ax == bx && ay == by) return 0; if (ax < bx || (ax == bx && ay < by)) return -1;
就像我不喜欢使用return (0)
。
请注意,如果您定位.Net-3.5 +应用程序,则可以使用LINQ,这样可以更轻松,更快速地进行排序。
LINQ vesion可以是这样的:
var orderedList = Points.OrderBy(point => point.x) .ThenBy(point => point.y) .ToList();
public class CoordinatesBasedComparer : IComparer, IComparer { public int Compare(Point a, Point b) { if ((ax == bx) && (ay == by)) return 0; if ((ax < bx) || ((ax == bx) && (ay < by))) return -1; return 1; } int IComparer.Compare(Object q, Object r) { return Compare((Point)q, (Point)r); } }
如果你像我一样慢,那么使用IComparer
时-1和1很难推理。 考虑它的方法是当x
应该先行,返回-1。 当y
应该先行时,返回1。
如果你有很多字段需要排序,它仍然会让人感到困惑。 您可以使用Enum
使比较逻辑比1和-1更具可读性,然后转换结果。
此示例将前面具有最少量空字段的对象放在前面。
public class NullishObjectsToTheBackOfTheLine: IComparer { 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; } }
在将类型为MyClass
的对象添加到SortedList
我收到了InvalidOperation
错误。 我错误地实现了IComparer接口。 我需要实现的是使用CompareTo(MyClass other)方法的IComparable,而不是ICompare.Compare(MyClass x,MyClass y)。 这是一个简化的例子:
SortedList sortedList = new SortedList (); 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 { int IComparable .CompareTo(MyClass other) { // DoCompareFunction(this, other); and return -1,0,1 } }
这被打破了(如果添加到SortedList
不要这样做) :
public class MyClass : IComparer { int IComparable .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值)