2010-03-04 15 views
12

¿Cómo puedo realizar una clasificación con dos criterios diferentes?Ordenar con dos criterios, cadena ascendente, int ascendente

Por ejemplo, I tienen objetos persona como:

Person con propiedades FirstName (string), LastName, y Rank (int).

Datos de ejemplo, así:

Xavier Smith 1 
Alexander Smith 2 
Alexander Smith 1 
Bob  Hawke 2 

Debe ordenar en FirstName alfabéticamente, a continuación, en el rango, por ejemplo, resultante:

Alexander Smith 1 
Alexander Smith 2 
Bob  Hawke 2 
Xavier Smith 1 

Hasta ahora, he intentado lo siguiente, pero no está funcionando apropiadamente:

peopleList es List<Person>

peopleList.Sort(new Comparison<Person>((x,y) => x.Rank.CompareTo(y.Rank))); 
peopleList.Sort(new Comparison<Person>((x, y) => string.Compare(x.Name, y.Name))); 

Gracias

edición: a Evitar cambiar demasiado mi código, realmente quiero mantener la lista, si cambio las líneas anteriores a:

peopleList.OrderBy(person => person.FirstName).ThenBy(person => person.Rank).ToList(); 

Daría la misma lista que acaba de ordenar correctamente, ¿correcto?

Respuesta

18

Enfoque LINQ

Con LINQ puede utilizar OrderBy y ThenBy:

var result = peopleList.OrderBy(p => p.FirstName).ThenBy(p => p.Rank); 

Esto devolverá un IEnumerable<T>. Si realmente necesita un List<T> agregue un .ToList() al final.

Si desea utilizar el método Sort, deberá escribir un comparador personalizado.

EDITAR: utilizando ToList() devuelve una nueva lista. Si desea ordenar su lista existente, entonces debe usar el método Sort que no devuelve una lista, sino que opera en la lista actual (es un método void).

Ordenar/Comparer Enfoque

Uso: list.Sort(new PersonComparer());

Aquí está el código comparador. Fue adaptado del MSDN example, así que recomiendo leer los comentarios que utilizaron para entender por qué está estructurado de esta manera.

public class PersonComparer : IComparer<Person> 
{ 
    public int Compare(Person x, Person y) 
    { 
     if (x == null) 
     { 
      if (y == null) 
      { 
       return 0; 
      } 
      else 
      { 
       return -1; 
      } 
     } 
     else 
     { 
      if (y == null) 
      { 
       return 1; 
      } 
      else 
      { 
       int retval = x.FirstName.CompareTo(y.FirstName); 

       if (retval != 0) 
       { 
        return retval; 
       } 
       else 
       { 
        return x.Rank.CompareTo(y.Rank); 
       } 
      } 
     } 
    } 
} 
+0

Realmente debo leer mucho más sobre LINQ, ¡parece estar haciendo mi vida mucho más fácil! – baron

+0

@baron ver mi edición, comenté su pregunta en su edición reciente. –

+0

@baron Agregué un comparador que se puede usar con 'Sort()'. –

3

Me gusta la respuesta LINQ.Si eso no es una opción, siempre se puede utilizar

(x,y) => 2*string.Compare(x.Name,y.Name) + x.Rank.CompareTo(y.Rank) 

para que la cadena comparar siempre domina a menos que sea igual a 0

3

Usted fue realmente muy estrecha con la sintaxis lambda en el lugar de clasificación. Estás sólo falta el hecho de que lambdas pueden estar encerrados en su propio ámbito:

peopleList.Sort(new Comparison<Person>((x,y) => 
{ 
    int result = x.FirstName.CompareTo(y.FirstName); 
    return (result != 0) ? result : x.Rank.CompareTo(y.Rank); 
})); 

que es un poco menos esfuerzo que escribir su propia IComparer<Person>!

+0

ahhhh .... ¡Gracias! Sabiendo que eso ayudará con un montón de mi código existente:) – baron

+0

@Aaronaught es muy agradable, pero debes voltear la comparación. Compare FirstName primero, luego en la segunda parte de la comparación ternaria Rank. –

+0

@Ahmad: Vaya, ayuda a leer la pregunta eh. Solucionado eso. – Aaronaught

5

Las otras respuestas parecen ser más elegantes que esto y me hacen sentir como un novato, sin embargo, si usted entiende cómo ordenar de esta manera, puede ordenar cualquier tipo de lista sin saber mucho de nada . Y no es necesario escribir una clase completamente nueva (aunque escribir una clase de comparador puede ser útil si ordena otras listas similares en otras partes de su código).

peopleList.Sort((x, y) => 
    { 
     int compare = x.FirstName.CompareTo(y.FirstName); 
     if (compare != 0) 
      return compare; 

     compare = x.Rank.CompareTo(y.Rank); 
     if (compare != 0) 
      return compare; 

     return x.LastName.CompareTo(y.LastName); 
    }); 
Cuestiones relacionadas