2009-05-29 28 views
36

Esta es una lista y estoy tratando de encontrar una manera eficiente de ordenar esta lista List CarList, que contiene 6 (o cualquier cantidad entera) Cars, por la fecha de fabricación del auto. Iba a hacer Bubble sort, pero ¿funcionará? ¿Alguna ayuda?Ordenando una lista de objetos en C#

Gracias

+2

(fuera del tema) Autoproperties anyone? –

+2

@Peter Lillevold - ese fue mi PRIMER PENSAMIENTO también. No he escrito una propiedad "normal" (respaldada por una variable local que escribí) en mucho tiempo. (Solo para que mike sepa: "DateTime CreationDate {get; set;}" público es legal en C# 3.0) – Pwninstein

+1

Hm, presiono Alt-Enter en el editor para que ReSharper se convierta en propiedad automática ... pero no pasó nada. ohwell, ¿se considera grosero editar ejemplos de código como este? aunque es un poco arriesgado en este caso, ya que no estamos seguros de si @Mike está usando C# 3.0 o no .. –

Respuesta

83

La clase List<T> hace que este trivial para usted, ya que contiene un Sort method. (Utiliza el algoritmo QuickSort, no Bubble Sort, que en general es mejor de todos modos). Aún mejor, tiene una sobrecarga que toma un argumento Comparison<T>, lo que significa que puede pasar una expresión lambda y hacer las cosas muy simples.

Prueba esto:

CarList.Sort((x, y) => DateTime.Compare(x.CreationDate, y.CreationDate)); 
+1

Creo que él quiere ordenarlo, primero en automóvil, luego por marca, luego por fecha ... –

+1

@Eoin: Es un poco ambiguo, lo admito. Todavía creo que quiso decir "Car Make Date" como una propiedad, refiriéndose a 'CreationDate'. – Noldorin

+3

+1 de para usar expresiones lambda! –

16

El mejor enfoque es poner en práctica ya sea IComparable o IComparable<T>, y luego llamar a List<T>.Sort(). Esto hará todo el trabajo duro de ordenar por ti.

+2

+1 para contrarrestar el -1 sin sentido que hizo otra persona. No hay nada malo con esta sugerencia. – tomfanning

+3

Sin embargo, un ejemplo de código hubiera sido bueno. – Peter

55

Se podría utilizar LINQ:

listOfCars.OrderBy(x => x.CreationDate); 

EDIT: Con este enfoque, es fácil añadir más columnas de orden:

listOfCars.OrderBy(x => x.CreationDate).ThenBy(x => x.Make).ThenBy(x => x.Whatever); 
+4

Sí, esto también hará el trabajo. Sin embargo, tendrá un rendimiento peor que el uso de List.Sort, ya que se basa en LINQ (es decir, objetos IEnumerable ), aunque a partir de la pregunta original que no parece ser un gran problema. La única diferencia real es que esto devuelve un nuevo objeto (que luego debe convertir a una lista usando 'ToList()'), mientras que List.Sort realiza el ordenamiento en la instancia actual. – Noldorin

+0

@Noldorin. Sí, tu sugerencia de utilizar List.Sort (comparando) podría ser más rápida ... –

+0

Gracias, no sabía nada de ThenBy. –

14

Otra opción sería utilizar un comparador personalizado:

using System; 
using System.Collections.Generic; 
using System.Text; 

namespace Yournamespace 
{ 
    class CarNameComparer : IComparer<Car> 
    { 
     #region IComparer<Car> Members 

     public int Compare(Car car1, Car car2) 
     { 
     int returnValue = 1; 
     if (car1 != null && car2 == null) 
     { 
      returnValue = 0; 
     } 
     else if (car1 == null && car2 != null) 
     { 
      returnValue = 0; 
     } 
     else if (car1 != null && car2 != null) 
     { 
      if (car1.CreationDate.Equals(car2.CreationDate)) 
      { 
       returnValue = car1.Name.CompareTo(car2.Name); 
      } 
      else 
      { 
       returnValue = car2.CreationDate.CompareTo(car1.CreationDate); 
      } 
     } 
     return returnValue; 
     } 

     #endregion 
    } 
} 

que llamas así:

yourCarlist.Sort(new CarNameComparer()); 

Nota: No compilar este código lo que es posible que tenga que quitar

Edición de error de máquina modificada de modo que el comparador compara el creationdate conforme a lo solicitado en cuestión.

+0

¡Nada de malo en esto, pero mucho más de lo que necesita! – Noldorin

+0

Modifiqué mi respuesta para que coincida con su comentario. Es el camino a seguir para tener un control total sobre la clasificación. Pero eso puede ser demasiado en este caso :-) – Peter

+0

Es una buena respuesta de todos modos, ya que es traducible a otros idiomas también. Cuando usas expresiones linq o lambda, te atrapas en C#. _ (aunque estoy muy tentado de no hacer mucho en este momento y solo uso la 1 línea de lambda:) _ – Bitterblue

1

evitaría escribir mi propio algoritmo de clasificación, pero si se va de todos modos, echar un vistazo a algunos de http://www.sorting-algorithms.com/ comparrisons de diferentes algoritmos de ordenación ...

6

me acaba de utilizar la estructura en list.sort método. Utiliza el algoritmo QuickSort que, en promedio, se ejecuta en O (n log n).

Este código debería funcionar para usted, cambio sus propiedades a auto-propiedades y definí un método estático CompareCarSpecs que solo usa el método DateTime.CompareTo ya existente.

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<CarSpecs> cars = new List<CarSpecs>(); 
     cars.Sort(CarSpecs.CompareCarSpecs); 
    } 
} 

public class CarSpecs 
{ 
    public string CarName { get; set; } 
    public string CarMaker { get; set; } 
    public DateTime CreationDate { get; set; } 

    public static int CompareCarSpecs(CarSpecs x, CarSpecs y) 
    { 
     return x.CreationDate.CompareTo(y.CreationDate); 
    } 
} 

Espero que esto ayude.

+0

Esta es una buena solución si no tiene C# 3.0 disponible (es decir, sin lambdas). – Noldorin

3

Poniendo algunas de las piezas mencionadas aquí juntas. Esto compila y funciona en C# 4.xy VS2010. Probé con un WinForm. Añada el método al WinFormMain(). Necesitará al menos los ensamblajes System.Linq y System.Generic.Collection s.

private void SortCars() 
    { 
     List<CarSpecs> cars = new List<CarSpecs>(); 
     List<CarSpecs> carsSorted = new List<CarSpecs>(); 

     cars.Add(new CarSpecs 
     { 
      CarName = "Y50", 
      CarMaker = "Ford", 
      CreationDate = new DateTime(2011, 4, 1), 
     }); 

     cars.Add(new CarSpecs 
     { 
      CarName = "X25", 
      CarMaker = "Volvo", 
      CreationDate = new DateTime(2012, 3, 1), 
     }); 

     cars.Add(new CarSpecs 
     { 
      CarName = "Z75", 
      CarMaker = "Datsun", 
      CreationDate = new DateTime(2010, 5, 1), 
     }); 

     //More Comprehensive if needed 
     //cars.OrderBy(x => x.CreationDate).ThenBy(x => x.CarMaker).ThenBy(x => x.CarName); 

     carsSorted.AddRange(cars.OrderBy(x => x.CreationDate)); 

     foreach (CarSpecs caritm in carsSorted) 
     { 
      MessageBox.Show("Name: " +caritm.CarName 
       + "\r\nMaker: " +caritm.CarMaker 
       + "\r\nCreationDate: " +caritm.CreationDate); 
     } 
    } 
} 

public class CarSpecs 
{ 
    public string CarName { get; set; } 
    public string CarMaker { get; set; } 
    public DateTime CreationDate { get; set; } 
}