我有一个list-generic,它有一个属性(类类型)。我需要一个Z参数的排序方法(TrainingSet):
public override List<TrainingSet> CalculatedDistancesArray
(List<TrainigSet> ts, double x, double y, int k)
{
for (int i =0; i < ts.Count; i++)
{
ts[i].Z = (Math.Sqrt(Math.Pow((ts[i].X - x), 2)
+ Math.Pow((ts[i].Y - y), 2)));
}
// I want to sort according to Z
ts.Sort(); //Failed to compare two elements in the array.
List<TrainingSet> sortedlist = new List<TrainingSet>();
for (int i = 0; i < k; i++)
{
sortedlist.Add(ts[i]);
}
return ts;
}
public class TrainigSet
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public string Risk { get; set; }
}
答案 0 :(得分:20)
只需对单个属性进行排序即可。使用带Comparison<T>
:
// C# 2
ts.Sort(delegate (TrainingSet o1, TrainingSet o2)
{ return o1.Z.CompareTo(o2.Z)); }
);
// C# 3
ts.Sort((o1, o2) => o1.Z.CompareTo(o2.Z));
对多个属性进行排序有点棘手。我有类以复合方式构建比较,以及构建“投影比较”,但如果你真的只想按Z排序,那么上面的代码将变得如此简单。
如果您使用的是.NET 3.5,并且您并不真正需要在列表中进行排序,则可以使用OrderBy和ThenBy,例如
return ts.OrderBy(t => t.Z);
或进行更复杂的比较:
return ts.OrderBy(t => t.Z).ThenBy(t => t.X);
这些将由查询表达式中的orderby
子句表示:
return from t in ts
orderby t.Z
select t;
和
return from t in ts
orderby t.Z, t.X
select t;
(如果需要,您也可以按降序排序。)
答案 1 :(得分:3)
var sortedList =
list.OrderBy(i => i.X).ThenBy(i => i.Y).ThenBy(i => i.Z).ToList();
答案 2 :(得分:1)
你可以试试这个。它对我有用:
ts.Sort(delegate(TrainingSet a, TrainingSet b) { return a.X.CompareTo(b.X) != 0 ? a.X.CompareTo(b.X) : a.Y.CompareTo(b.Y); });
答案 3 :(得分:0)
使用框架3.5,这只是:
public override List<TrainingSet> CalculatedDistancesArray(List<TrainigSet> ts, double x, double y, int k) {
foreach (TrainigSet t in ts) {
t.Z = Math.Sqrt(Math.Pow(t.X - x, 2) + Math.Pow(t.Y - y, 2));
}
return ts.OrderBy(t => t.Z).Take(k).ToList();
}
注意:这不会改变ts列表的顺序,而是创建一个新的有序列表以便返回。
(我假设您实际上想要从列表中返回前k个项目,而不是像在问题中的代码中那样返回ts列表。)
使用框架2需要更多代码:
public override List<TrainingSet> CalculatedDistancesArray(List<TrainigSet> ts, double x, double y, int k) {
foreach (TrainigSet t in ts) {
t.Z = Math.Sqrt(Math.Pow(t.X - x, 2) + Math.Pow(t.Y - y, 2));
}
ts.Sort(delegate (TrainigSet t1, TrainigSet t2) { return t1.Z.CompareTo(t2.Z)); });
List<TrainigSet> result = new List<TrainigSet>(k);
for (int i = 0; i < k ; i++) {
result.Add(ts[i]);
}
return result;
}
如果您仅将Z值用于排序,则可以跳过Math.Sqrt
调用,并将该值保留为距离的平方,因为它与距离完全相同。
答案 4 :(得分:0)
如果您实现IComparable&lt; TrainingSet&gt;,则可以在列表中使用Sort方法。在您的类型“TrainingSet”上。您必须实现“CompareTo”方法。然后,您可以简单地将您的实现委托给双重类型Z的“CompareTo”。这将避免您的异常。