Ordina un elenco di classi personalizzate <T>


112

Vorrei ordinare la mia lista con la dateproprietà.

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

E questo è quello Listche voglio ordinare:

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

Quello che voglio fare è ordinare l'elenco in base alla dateproprietà della classe cTag. La data è nel formato: dd.MM.yyyy.

Ho letto qualcosa IComparablesull'interfaccia, ma non so come usarla.

Risposte:


143

Un modo per farlo è con un file 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); });

98
Puoi anche scrivere la stessa cosa con un'espressione lambda:list.Sort((a,b) => a.date.CompareTo(b.date));
Xavier Poinas

2
@Xavier per qualche motivo la mia mente salta sempre prima ai predicati, anche se hai ragione al 100% sul fatto che la tua espressione Lambda avrebbe svolto il lavoro ed è probabilmente più facile da leggere / capire.
ahsteele

come fa questo, o come faresti, a rompere un legame in modo coerente usando l'espressione lambda? E se a.date == b.date qui? list.Sort ((a, b) => a.date.CompareTo (b.date)); Questo creerebbe problemi quando le griglie di paging e queste due cadevano su pagine diverse?
TheEmirOfGroofunkistan

1
@TheEmirOfGroofunkistan che tutto dipende da come CompareToviene implementato. IComparablegarantisce che una classe avrà il metodo, ma il modo in cui lo fa il confronto dipende dal creatore della classe. Non sono sicuro di come Date implementi ICompare, ma spesso ho visto sviluppatori utilizzare i parametri dell'ordine che venivano passati per rompere un pareggio quando i valori sono uguali. hth
ahsteele

51

Hai ragione sul fatto che la tua classe cTag deve implementare l' IComparable<T>interfaccia. Quindi puoi semplicemente chiamare Sort()sulla tua lista.

Per implementare l' IComparable<T>interfaccia, è necessario implementare il CompareTo(T other)metodo. Il modo più semplice per farlo è chiamare il metodo CompareTo del campo che si desidera 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 ordinerebbe bene, perché userebbe l'ordinamento classico sulle stringhe (dato che hai dichiarato la 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 rimarrebbe 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 dovresti fare quando crei l'istanza della classe per convertire la tua stringa contenente la data nel tipo DateTime, ma può essere fatto facilmente, ad esempio con il DateTime.Parse(String)metodo.


38

In questo caso puoi anche ordinare usando LINQ:

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

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

9

Per prima cosa, se la proprietà date sta memorizzando una data, memorizzala usando un DateTime. Se analizzi la data attraverso l'ordinamento, devi analizzarla per ogni elemento confrontato, non è molto efficiente ...

Puoi quindi creare 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());

Puoi anche farlo come 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;
          });

6

Hai ragione: devi implementare IComparable. Per fare ciò, dichiara semplicemente la tua classe:

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

In CompareTo, devi solo implementare il tuo algoritmo di confronto personalizzato (puoi usare gli oggetti DateTime per farlo, ma assicurati di controllare prima il tipo di "obj"). Per ulteriori informazioni, vedere qui e qui .


7
IComparable<T>sarebbe probabilmente una scelta migliore, in quanto è selezionata preferibilmente a IComparable: msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
Richard Szalay

5

Puoi usare linq:

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

3

guarda il metodo Sort sovraccarico della classe List. ci sono alcuni modi per farlo. uno di questi: la tua classe personalizzata deve implementare l'interfaccia IComparable, quindi utilizzi il metodo Sort della classe List.


3

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


2
YourVariable.Sort((a, b) => a.amount.CompareTo(b.amount));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.