2009-05-29 12 views
36
public class CarSpecs 
{ 
    public String CarName { get; set; } 

    public String CarMaker { get; set; } 

    public DateTime CreationDate { get; set; } 
} 

Questa è una lista e sto cercando di trovare un modo efficiente per ordinare questo elenco Elenco CarList, contenente 6 (o qualsiasi numero intero) Automobili, entro la data Car Make. Stavo per fare Bubble sort, ma funzionerà? Qualsiasi aiuto?Ordinamento di un elenco di oggetti in C#

Grazie

+2

(off-topic) Autoproprietà chiunque? –

+2

@Peter Lillevold - anche questo è stato il mio MIO PRIMO PENSIERO. Non ho scritto una proprietà "normale" (supportata da una variabile locale che ho scritto) in un tempo mooolto. (Solo così mike sa: "public DateTime CreationDate {get; set;}" è legale in C# 3.0) – Pwninstein

+1

Hm, premo Alt-Invio nell'editor per fare convertire ReSharper in autoproprietà ... ma non è successo nulla. oh, è considerato maleducato modificare esempi di codice come questo? anche se un po 'rischioso in questo caso dal momento che non siamo sicuri se @Mike stia usando C# 3.0 o no .. –

risposta

83

La classe List<T> rende questo banale per voi, in quanto contiene un Sort method. (Utilizza l'algoritmo QuickSort, non Bubble Sort, che in genere è comunque migliore.) Ancora meglio, ha un sovraccarico che accetta un argomento Comparison<T>, il che significa che è possibile passare un'espressione lambda e rendere le cose davvero molto semplici.

Prova questo:

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

Penso che lui voglia ordinare, prima con Car, poi con Make, poi con Date ... –

+1

@Eoin: È un po 'ambiguo, lo ammetto. Credo ancora che intendesse "Car Make Date" come una proprietà, riferendosi a "CreationDate". – Noldorin

+3

+1 per aver usato le espressioni lambda! –

16

L'approccio migliore è quello di implementare sia IComparable o IComparable<T>, e quindi chiamare List<T>.Sort(). Questo farà tutto il duro lavoro di selezione per te.

+2

+1 per contrastare l'inutile -1 che qualcun altro ha fatto. Niente di male in questo suggerimento. – tomfanning

+3

Un esempio di codice sarebbe stato comunque carino. – Peter

55

Si potrebbe usare LINQ:

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

EDIT: Con questo approccio, la sua facile aggiungere su più colonne di ordinamento:

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

Sì, questo farà anche il lavoro. Avrà tuttavia prestazioni peggiori rispetto all'utilizzo di List.Sort, poiché si basa su LINQ (cioè oggetti IEnumerable ), sebbene dalla domanda originale non sembrerebbe un grosso problema. L'unica vera differenza è che questo restituisce un nuovo oggetto (che poi devi convertire in una lista usando 'ToList()'), mentre List.Sort esegue l'ordinamento nell'istanza corrente. – Noldorin

+0

@Noldorin. Sì, il tuo suggerimento di usare List.Sort (comparison) potrebbe essere più veloce ... –

+0

Grazie, non sapevo di ThenBy. –

14

Un'altra opzione sarebbe quella di utilizzare un operatore di confronto personalizzato:

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

che si chiama in questo modo:

yourCarlist.Sort(new CarNameComparer()); 

Nota: Non ho compilare il codice in modo che potrebbe essere necessario rimuovere di errore di battitura

Edit: modificato così l'operatore di confronto confronta il dell'emissione come richiesto in questione.

+0

Niente di sbagliato in questo, ma molto più del necessario! – Noldorin

+0

Modificata la mia risposta per abbinare il tuo commento. È il modo di avere il pieno controllo sull'ordinamento. Ma potrebbe essere troppo in questo caso :-) – Peter

+0

È comunque una buona risposta poiché è traducibile anche in altre lingue. Quando usi espressioni linq o lambda, ti intrappoli in C#. _ (anche se sono molto tentato di non fare molto adesso e usare solo la linea 1 di lambda:) _ – Bitterblue

1

Vorrei evitare di scrivere il mio algoritmo di ordinamento, ma se avete intenzione di in ogni caso, dare un'occhiata a http://www.sorting-algorithms.com/ per alcune comparrisons di diversi algoritmi di ordinamento ...

6

vorrei solo usare la configurazione in list.sort metodo. Utilizza l'algoritmo QuickSort che in media viene eseguito in O (n log n).

Questo codice dovrebbe funzionare per voi, cambio le proprietà in proprietà automatiche e definito un metodo CompareCarSpecs statico che utilizza solo il metodo DateTime.CompareTo già esistente.

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

Spero che questo aiuti.

+0

Questa è una buona soluzione se non hai C# 3.0 disponibile (cioè non lambda). – Noldorin

3

Mettere alcuni dei pezzi menzionati qui insieme. Questo compila e funziona in C# 4.xe VS2010. Ho provato con uno WinForm. Quindi aggiungi il metodo allo WinFormMain(). Avrai bisogno degli assembly System.Linq e System.Generic.Collection almeno.

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