2009-05-09 16 views
6

Tengo una lista genérica que tiene una propiedad (tipo de clase). Necesito un método de clasificación para los parámetros Z (TrainingSet):¿Cómo ordenar la lista tipo genérica si hay más de una propiedad?

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

Tenga en cuenta que hay maneras más fáciles de copiar una lista, por cierto - y no que realmente significa para ordenar la entrada de la lista * * y luego copiarlo en una nueva lista? –

+0

No está copiando toda la lista, solo los primeros k elementos. – Guffa

Respuesta

20

Sólo la clasificación en una sola propiedad es fácil. Utilice la sobrecarga que tiene un 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)); 

clasificación en múltiples propiedades es un poco más complicado. Tengo clases para construir comparaciones de una manera compuesta, así como para construir "comparaciones de proyección", pero si realmente solo quieres ordenar por Z, el código anterior será tan fácil como sea posible.

Si está utilizando .NET 3.5 y realmente no necesita que la lista se ordene in situ, puede usar OrderBy y ThenBy, p.

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

o para una comparación más complicado:

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

Estos estarían representados por orderby cláusulas en una expresión de consulta:

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

y

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

(Usted poder . También especie de manera descendente si quieres)

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

necesito códigos web 2.0. No tengo web 3.5 – Penguen

+0

Tenga en cuenta que esto no ordena la lista en su lugar, que el OP * puede * querer, no está claro. –

+0

@ykaratoprak: ver la respuesta de Jon Skeet. Él tiene una versión 2.0. –

0

Usando Framework 3.5 esta sería simplemente:

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

Nota: Esto no va a cambiar el orden de la lista ts, pero crear una nueva lista ordenada regresar.

(supongo que en realidad quería devolver los primeros k artículos de la lista, no la lista ts como lo hace en el código en su pregunta.)

Usando marco 2 necesita un poco más de código:

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 está utilizando el valor Z exclusivamente para la clasificación, puede omitir la llamada Math.Sqrt y acaba de salir del valor a ser el cuadrado de la distancia, como que clasifica exactamente la misma que la distancia.

0

Podrá utilizar el método Sort en la lista si implementa el TrainingSet < de IComparable > en su tipo "TrainingSet". Deberá implementar un método "CompareTo". A continuación, puede simplemente delegar su implementación en "CompareTo" de su Z con doble letra. Esto evitará su excepción.

1

Puede probar esto. Se trabajó para mí:

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

Formatea tu código pls ... – Rajesh

Cuestiones relacionadas