2009-05-09 5 views
6

J'ai un liste-générique qui a une propriété (type de classe). J'ai besoin d'une méthode de tri pour les paramètres Z (TrainingSet):Comment faire pour trier le type de liste générique si plus d'une propriété?

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

Notez qu'il y a des manières plus faciles de copier une liste, au fait - et avez-vous vraiment voulu trier la liste * d'entrée * et puis la copiez vers une nouvelle liste? –

+0

Il ne copie pas la liste entière, seulement les premiers k objets. – Guffa

Répondre

20

tri Juste sur une seule propriété est facile. Utilisez la surcharge qui prend 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)); 

tri sur plusieurs propriétés est un peu plus compliqué. J'ai des classes pour construire des comparaisons d'une manière composée, ainsi que construire des "comparaisons de projections" mais si vous voulez vraiment seulement trier par Z alors le code ci-dessus va être aussi facile que possible.

Si vous utilisez .NET 3.5 et que vous n'avez pas vraiment besoin de trier la liste sur place, vous pouvez utiliser OrderBy et ThenBy, par exemple.

return ts.OrderBy(t => t.Z); 

ou pour une comparaison plus compliquée:

return ts.OrderBy(t => t.Z).ThenBy(t => t.X); 

Ceux-ci seraient représentés par orderby clauses dans une expression de requête:

return from t in ts 
     orderby t.Z 
     select t; 

et

return from t in ts 
     orderby t.Z, t.X 
     select t; 

(Vous pouvez . Également trier de manière descendante si vous voulez)

3
var sortedList = 
     list.OrderBy(i => i.X).ThenBy(i => i.Y).ThenBy(i => i.Z).ToList(); 
+0

J'ai besoin de codes web 2.0. Je n'ai pas de web 3.5 – Penguen

+0

Notez que cela ne permet pas de trier la liste, ce que l'OP * peut * vouloir - ce n'est pas clair. –

+0

@ykaratoprak: Voir la réponse de Jon Skeet. Il a une version 2.0. –

0

En utilisant Framework 3.5 ce serait simplement:

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(); 
} 

Note: Cela ne changera pas l'ordre de la liste ts, mais créer une nouvelle liste triée revenir.

(je suppose que vous vouliez réellement revenir les premiers éléments de k dans la liste, pas la ts liste comme vous le faites dans le code dans votre question.)

utilisant le framework 2 a besoin d'un peu plus de code:

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; 
} 

Si vous utilisez la valeur Z uniquement pour le tri, vous pouvez ignorer l'appel Math.Sqrt et il suffit de laisser la valeur à la place de la distance, en triant exactement la même que la distance.

0

Vous pourrez utiliser la méthode Sort sur la liste si vous implémentez IComparable <TrainingSet> sur votre type "TrainingSet". Vous devrez implémenter une méthode "CompareTo". Vous pouvez alors simplement déléguer votre implémentation au "CompareTo" de votre Z double-tapé. Cela évitera votre exception.

1

Vous pourriez essayer ceci. Cela a fonctionné pour moi:

ts.Sort(delegate(TrainingSet a, TrainingSet b) { return a.X.CompareTo(b.X) != 0 ? a.X.CompareTo(b.X) : a.Y.CompareTo(b.Y); }); 
+0

Formater votre code pls ... – Rajesh

Questions connexes