2010-07-02 1 views
95

Desidero ordinare la mia lista con la proprietà date.Ordinamento di un elenco di classi personalizzate <T>

Questa è la mia classe personalizzata:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace Test.Web 
{ 
    public class cTag 
    { 
     public int id { get; set; } 
     public int regnumber { get; set; } 
     public string date { get; set; } 
    } 
} 

Un Questo è il List che voglio sorta:

List<cTag> Week = new List<cTag>(); 

Quello che voglio fare è ordinare l'elenco per la date proprietà del CTAG classe. La data è nel formato: gg.mm.aaaa.

Ho letto qualcosa sull'interfaccia IComparable, ma non so come usarlo.

risposta

118

Un modo per farlo è con un delegate

List<cTag> week = new List<cTag>(); 
// add some stuff to the list 
// now sort 
week.Sort(delegate(cTag c1, cTag c2) { return c1.date.CompareTo(c2.date); }); 
+81

È anche possibile scrivere la stessa cosa con un'espressione lambda: 'list.Sort ((a, b) => a.date.CompareTo (b.date));' –

+0

@Xavier per qualche motivo la mia mente ancora salta sempre ai predicati per primo, anche se sei corretto al 100% che la tua espressione Lambda avrebbe svolto il lavoro ed è probabilmente più facile da leggere/capire. – ahsteele

+0

come fa questo, o in che modo, rompendo una cravatta in modo coerente usando l'espressione lambda? Cosa succede se a.date == b.date qui? list.Sort ((a, b) => a.date.CompareTo (b.date)); Questo creerebbe problemi quando si cercavano le griglie e questi due capitati cadevano su pagine diverse? – TheEmirOfGroofunkistan

3

look over overload Metodo di ordinamento della classe List. ci sono alcuni modi per farlo. uno di essi: la classe personalizzata deve implementare l'interfaccia IComparable, quindi si utilizza il metodo Sort della classe List.

5

Hai ragione - è necessario implementare IComparable. Per farlo, è sufficiente dichiarare la classe:

public MyClass : IComparable 
{ 
    int IComparable.CompareTo(object obj) 
    { 
    } 
} 

In CompareTo, basta implementare l'algoritmo di confronto personalizzato (è possibile utilizzare oggetti DateTime per fare questo, ma solo essere certi di controllare il tipo di "obj" prima) . Per ulteriori informazioni, vedere here e here.

+7

'IComparable ' potrebbe essere una scelta migliore, poiché è preferibile a 'IComparable': http://msdn.microsoft.com/en-us/library/b0zbh7b6.aspx –

+0

Si impara qualcosa ogni giorno ...: o) –

10
List<cTag> week = new List<cTag>(); 
week.Sort((x, y) => 
    DateTime.ParseExact(x.date, "dd.MM.yyyy", CultureInfo.InvariantCulture).CompareTo(
    DateTime.ParseExact(y.date, "dd.MM.yyyy", CultureInfo.InvariantCulture)) 
); 
5

È possibile utilizzare LINQ:

var q = from tag in Week orderby Convert.ToDateTime(tag.date) select tag; 
List<cTag> Sorted = q.ToList() 
32

Per questo caso sarà anche possibile ordinare utilizzando LINQ:

week = week.OrderBy(w => DateTime.Parse(w.date)).ToList(); 
5

Per prima cosa, se la proprietà data sta memorizzando una data, negozio usando un DateTime. Se si analizza la data attraverso il genere bisogna analizzarlo per ogni elemento a confronto, che non è molto efficiente ...

È quindi possibile fare un IComparer:

public class TagComparer : IComparer<cTag> 
{ 
    public int Compare(cTag first, cTag second) 
    { 
     if (first != null && second != null) 
     { 
      // We can compare both properties. 
      return first.date.CompareTo(second.date); 
     } 

     if (first == null && second == null) 
     { 
      // We can't compare any properties, so they are essentially equal. 
      return 0; 
     } 

     if (first != null) 
     { 
      // Only the first instance is not null, so prefer that. 
      return -1; 
     } 

     // Only the second instance is not null, so prefer that. 
     return 1; 
    } 
} 

var list = new List<cTag>(); 
// populate list. 

list.Sort(new TagComparer()); 

Si può anche fare come un delegato:

list.Sort((first, second) => 
      { 
       if (first != null && second != null) 
        return first.date.CompareTo(second.date); 

       if (first == null && second == null) 
        return 0; 

       if (first != null) 
        return -1; 

       return 1; 
      }); 
43

Lei ha ragione che la classe deve implementare CTAG IComparable<T> interfaccia. Quindi puoi semplicemente chiamare Sort() nella tua lista.

Per implementare l'interfaccia IComparable<T>, è necessario implementare il metodo CompareTo(T other). Il modo più semplice per farlo è chiamare il metodo CompareTo del campo che desideri confrontare, che nel tuo caso è la data.

public class cTag:IComparable<cTag> { 
    public int id { get; set; } 
    public int regnumber { get; set; } 
    public string date { get; set; } 
    public int CompareTo(cTag other) { 
     return date.CompareTo(other.date); 
    } 
} 

Tuttavia, questo non sarebbe sorta bene, perché questo avrebbe usato l'ordinamento classico sulle corde (da quando hai dichiarato data come stringa).Quindi penso che la cosa migliore da fare sarebbe ridefinire la classe e dichiarare la data non come stringa, ma come DateTime. Il codice sarebbe rimasto quasi lo stesso:

public class cTag:IComparable<cTag> { 
    public int id { get; set; } 
    public int regnumber { get; set; } 
    public DateTime date { get; set; } 
    public int CompareTo(cTag other) { 
     return date.CompareTo(other.date); 
    } 
} 

L'unica cosa che avrebbe dovuto fare quando si crea l'istanza della classe per convertire la stringa contenente la data in tipo DateTime, ma può essere fatto facilmente per esempio con il metodo DateTime.Parse(String).

2

Grazie per tutte le risposte veloci.

Questa è la mia soluzione:

Week.Sort(delegate(cTag c1, cTag c2) { return DateTime.Parse(c1.date).CompareTo(DateTime.Parse(c2.date)); }); 

Grazie

0

YourVariable.Sort ((a, b) => a.amount.CompareTo (b.amount));