Sortieren Sie eine benutzerdefinierte Klassenliste <T>

112

Ich möchte meine Liste mit der dateEigenschaft sortieren .

Dies ist meine benutzerdefinierte Klasse:

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

Und das ist das List, was ich sortieren möchte:

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

Ich möchte die Liste nach der dateEigenschaft der cTag-Klasse sortieren. Das Datum hat das Format: dd.MM.yyyy.

Ich habe etwas über die IComparableBenutzeroberfläche gelesen, weiß aber nicht, wie ich sie verwenden soll.

Werwölfe
quelle

Antworten:

143

Eine Möglichkeit, dies zu tun, ist mit einem 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); });
ahsteele
quelle
98
Sie können dasselbe auch mit einem Lambda-Ausdruck schreiben:list.Sort((a,b) => a.date.CompareTo(b.date));
Xavier Poinas
2
@ Xavier Aus irgendeinem Grund springt mein Verstand immer noch zuerst zu Prädikaten, obwohl Sie zu 100% richtig sind, dass Ihr Lambda-Ausdruck die Arbeit erledigen würde und wahrscheinlich leichter zu lesen / zu verstehen ist.
Ahsteele
Wie funktioniert das oder wie würden Sie eine Krawatte konsequent mit dem Lambda-Ausdruck brechen? Was ist, wenn a.date == b.date hier ist? list.Sort ((a, b) => a.date.CompareTo (b.date)); Würde dies Probleme verursachen, wenn Paging-Raster und diese beiden zufällig auf verschiedene Seiten fallen?
TheEmirOfGroofunkistan
1
@TheEmirOfGroofunkistan, dass alles davon abhängt, wie CompareToimplementiert wird. IComparableStipendiaten, dass eine Klasse über die Methode verfügt, aber wie sie diesen Vergleich durchführt, hängt vom Klassenersteller ab. Ich bin mir nicht sicher, wie Date ICompare implementiert, aber ich habe oft gesehen, dass Entwickler die Auftragsparameter verwendet haben, um eine Bindung zu lösen, wenn die Werte gleich sind. hth
ahsteele
51

Sie haben Recht, dass Ihre cTag-Klasse eine IComparable<T>Schnittstelle implementieren muss . Dann können Sie einfach Sort()auf Ihrer Liste anrufen .

Um die IComparable<T>Schnittstelle zu implementieren , müssen Sie die CompareTo(T other)Methode implementieren . Der einfachste Weg, dies zu tun, besteht darin, die CompareTo-Methode des Feldes aufzurufen, das Sie vergleichen möchten. In Ihrem Fall handelt es sich dabei um das Datum.

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

Dies würde jedoch nicht gut sortieren, da dies die klassische Sortierung nach Zeichenfolgen verwenden würde (da Sie das Datum als Zeichenfolge deklariert haben). Ich denke, der beste Weg wäre, die Klasse neu zu definieren und das Datum nicht als Zeichenfolge, sondern als DateTime zu deklarieren. Der Code würde fast gleich bleiben:

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

Das einzige, was Sie tun müssen, wenn Sie die Instanz der Klasse erstellen, um Ihre Zeichenfolge mit dem Datum in den DateTime-Typ zu konvertieren. Dies kann jedoch problemlos durchgeführt werden, z DateTime.Parse(String). B. mithilfe einer Methode.

Ondra C.
quelle
38

In diesem Fall können Sie auch mit LINQ sortieren:

week = week.OrderBy(w => DateTime.Parse(w.date)).ToList();
Yakimych
quelle
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))
);
Darin Dimitrov
quelle
8

Das Wichtigste zuerst: Wenn die date-Eigenschaft ein Datum speichert, speichern Sie es mit einer DateTime. Wenn Sie das Datum durch die Sortierung analysieren, müssen Sie es für jedes verglichene Element analysieren, das ist nicht sehr effizient ...

Sie können dann einen IComparer erstellen:

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

Sie können es sogar als Delegierter tun:

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;
          });
Matthew Abbott
quelle
6

Sie haben Recht - Sie müssen IComparable implementieren. Dazu deklarieren Sie einfach Ihre Klasse:

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

In CompareTo implementieren Sie einfach Ihren benutzerdefinierten Vergleichsalgorithmus (Sie können dazu DateTime-Objekte verwenden, müssen jedoch zuerst den Typ "obj" überprüfen). Weitere Informationen finden Sie hier und hier .

AJ.
quelle
7
IComparable<T>wäre wahrscheinlich eine bessere Wahl, da es bevorzugt auf Folgendes überprüft wird IComparable: msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
Richard Szalay
5

Sie können linq verwenden:

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

Schauen Sie sich die überladene Sortiermethode der List-Klasse an. Es gibt einige Möglichkeiten, dies zu tun. Eine davon: Ihre benutzerdefinierte Klasse muss die IComparable-Schnittstelle implementieren, dann können Sie die Sortiermethode der List-Klasse verwenden.

Arseny
quelle
3

Vielen Dank für all die schnellen Antworten.

Das ist meine Lösung:

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

Vielen Dank

Werwölfe
quelle
2
YourVariable.Sort((a, b) => a.amount.CompareTo(b.amount));
Sansalk
quelle