用二维对象排序数组列表
本文关键字:对象 排序 数组 列表 二维 | 更新日期: 2023-09-27 18:09:55
我有一个ArrayList,其中我存储了10个对象,每个对象随机生成两个数字,我想按对象的Y值对列表进行排序。
Random rndm = new Random();
ArrayList CustomList = new ArrayList();
for (int i = 0; i < 10; i++)
{
Point LP = new Point(rndm.Next(50), rndm.Next(50));
CustomList.Add(LP);
}
PrintList(CustomList);
CustomList.Sort();
PrintList(CustomList);
Sort
方法抛出以下异常:
System.InvalidOperationException: The comparer threw an exception. ---> System.ArgumentException: At least one object must implement IComparable.
我认为它不起作用,因为Sort方法不能处理数组列表中的二维对象。我怎样才能使排序方法现在工作?
ArrayList CustomList = new ArrayList();
只是一个一维列表——Point
具有二维的事实与列表的维度无关。点的二维数组(Point[][]
)看起来像这样:
row col1 col2 col3
1 Point Point Point
2 Point Point Point
3 Point Point Point
问题是Point
默认不实现IComparable
接口。这是有意义的-你能分辨出(1,3)是大于还是小于(2,2)吗?如果按第一个坐标比较,它会更小,但如果按到原点的距离比较,它会更大。
PointComparer
类:
public class PointComparer : IComparer<Point> {
// return -1 if x is the smallest, 1 if y is the smallest, 0 if they're equal
public int Compare(Point x, Point y) {
return x.Y.CompareTo(y.Y);
}
}
声明你的CustomList
为
List<Point> CustomList = new List<Point>();
,用
排序CustomList.Sort(new PointComparer());
最好的方法是使用List<Point>
,即使使用ArrayList
,您也可以使用LINQ:
Random rndm = new Random();
ArrayList CustomList = new ArrayList();
for (int i = 0; i < 10; i++)
{
Point LP = new Point(rndm.Next(50), rndm.Next(50));
CustomList.Add(LP);
}
var sorted = CustomList.Cast<Point>()
.OrderBy(p => p.Y)
.ToList();
如果您想将ArrayList
作为返回结构:
ArrayList sortedAL = new ArrayList(sorted);
原海报上写着:
Sort方法抛出以下异常:System.InvalidOperationException: The comparer threw an exception. ---> System.ArgumentException: At least one object must implement IComparable.
我认为它不起作用,因为Sort方法不能处理两个维ArrayLists。
你混淆了两点:
- 首先,它不能工作是因为异常消息告诉你的:
Point
类没有实现接口IComparable
。这意味着你的ArrayList
不知道如何比较两点:Point(1,2)
与Point(2,1
比较:第一个大于、小于或等于第二个?
-
第二,
ArrayList
只是一个数组——一个对象列表。它本身就是一维的。它是一个可调整的长度,相当于object[]
。 -
第三,出于以下几个原因,您应该避免使用非泛型集合类。
- 它们不是类型安全的,并且
- 泛型版本更容易使用,因为它们是强类型的:你不必将包含的引用向下转换为正确的类型。
那么,给定Point
的定义:
public struct Point
{
public int X { get ; set ; }
public int Y { get ; set ; }
public Point( int x , int y )
{
this.X = x ;
this.Y = y ;
}
}
你可以这样排序你的ArrayList
:
public class PointComparer : IComparer
{
int IComparer.Compare( object x , object y )
{
if ( x != null && !(x is Point) ) throw new ArgumentException();
if ( y != null && !(y is Point) ) throw new ArgumentException();
if ( x == null && y == null ) return 0 ; // two nulls are equals
else if ( x == null && y != null ) return -1 ; // we're collating nulls-low: change to +1 to collate nulls-high
else if ( x != null && y == null ) return +1 ; // we're collating nulls-low: change to -1 to collate nulls-high
else // both x and y are non-null
{
Point left = (Point) x ;
Point right = (Point) y ;
if ( left.Y < right.Y ) return -1 ;
else if ( left.Y > right.Y ) return +1 ;
else // ( left.Y == right.Y )
{
if ( left.X < right.X ) return -1 ;
else if ( left.X > right.X ) return +1 ;
else /* ( left.X == right.X ) */ return 0 ;
}
}
}
}
...
ArrayList listOfPoints = CreateListofPoints();
listOfPoints.Sort( new PointComparer() ) ;
或者您可以使用泛型集合来更简洁地完成相同的事情:
List<Point> listOfPoints = CreateListOfPoints();
listOfPoints.Sort( (left,right) => left.Y.CompareTo(right.Y) != 0
? left.Y.CompareTo(right.Y )
: left.X.CompareTo(right.X)
) ;