Использование IComparer для сортировки
Я пытаюсь использовать 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 ответов
вам нужно реализовать интерфейс strongly type (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();
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);
}
}
если вы медленный, как я, -1 и 1 может быть трудно рассуждать о При использовании IComparer
. Так думать об этом, когда 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; }
}
я получал InvalidOperation
ошибка при добавлении объекта типа MyClass
до SortedList<MyClass>
. Я неправильно реализовал интерфейс IComparer. То, что мне нужно было реализовать, было IComparable с методом CompareTo(MyClass other), а не ICompare.Сравнение (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
}
}
это была ошибка:
не удалось сравнить два элемента в массиве.
в системе.Коллекции.Родовой.ArraySortHelper ' 1.Ищет(Т[] массив, Индекс Int32, длина Int32, значение T, icomparer ' 1 comparer)
в системе.Матрица.BinarySearch[T] (T [] массив, индекс Int32, длина Int32, T значение, icomparer ' 1 comparer)
в системе.Коллекции.Родовой.SortedList ' 2.Добавить (клавиша TKey, Значение TValue)