我正在尝试使用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>
作为排序方法的参数
我需要做些什么来解决这个问题?
答案 0 :(得分:41)
您需要实现强类型接口(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 vesion可以是这样的:
var orderedList = Points.OrderBy(point => point.x)
.ThenBy(point => point.y)
.ToList();
答案 1 :(得分:12)
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);
}
}
答案 2 :(得分:5)
如果你像我一样慢,那么在使用IComparer
时,-1和1很难推理。考虑它的方法是在x
首先出现时,返回-1。当y
首先出现时,请返回1.
如果要排序的字段很多,它仍然会让人感到困惑。您可以使用Enum
使比较逻辑比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; }
}
答案 3 :(得分:0)
我在向InvalidOperation
添加MyClass
类型的对象时遇到SortedList<MyClass>
错误。我错误地实现了IComparer接口。我需要实现的是使用CompareTo(MyClass other)方法的IComparable,而不是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 value,IComparer`1 comparer)
at System.Collections.Generic.SortedList`2.Add(TKey key,TValue value)