Laden...

Wie List<T> nach bestimmten Kriterium sortieren?

Erstellt von bluedragon vor 14 Jahren Letzter Beitrag vor 14 Jahren 3.580 Views
B
bluedragon Themenstarter:in
101 Beiträge seit 2008
vor 14 Jahren
Wie List<T> nach bestimmten Kriterium sortieren?

Hallo liebe MyCSharp Gemeinde 😃

Erst einmal wünsche ich frohe Feiertage 😃

Aber ich hab mal wieder ein , ich glaube, Elementares Problem wo ich hängen bleibe.

Und zwar weiß ich nicht wie ich mit den drei Überladungen von List<T>.Sort() umgehen soll, bzw was diese können.
Ich möchte z.B. eine Liste die voller Objekte vom Typ "Chatter" , anhand des "Nicknames" sortieren. Hier ein Bespiel.


Class Chatter
{
     public string Nickname;
}

List<Chatter> chatter = new List<Chatter>();
Chatter a = new Chatter();
Chatter b = new Chatter();
Chatter c = new Chatter();
a.Nick = "hallo";
b.Nick = "test";
c.Nick = "beispiel";

chatter.AddRange(new Chatter[]{a,b,c});

chatter.Sort(); //kommt natürlich eine Exception, weil .NET nicht weiß anhand welschem Merkmal es sortieren soll 

Nun gibt es ja 3 weitere Überladungen von List<T>.Sort() und ich frage mich ob die nicht irgend wie dazu beitragen können, dass es möglich ist beim sortieren von Objekten eine public Variable(dieser Objekte) anzugeben und anhand dieser sollen dann die Objekte der Liste sortiert werden.

Womöglich ne dumme Frage, aber ich mache es mir bisher so umständlich die Nicknames in eine seperate Liste als Strings zu packen, diese dann zu sortieren und dann entsprechend Damit weiter zu arbeiten.

Lg bluedragon

Man muss viel gelernt haben, um nach etwas, worüber man nicht Bescheid weiß, richtig fragen zu können.

Wenn du jemandem vertrauen kannst, erübrigt sich ein Vertrag. Kannst du ihm nicht vertrauen, ist ein Vertrag nutzlos.

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo bluedragon,

mach deine Klasse IComparable<T> oder schreibe einen passenden IComparer<T>. Weiterführende Infos solltest du leicht finden.

herbivore

2.187 Beiträge seit 2005
vor 14 Jahren

Hallo bluedragon,

Ja:

  • Ja, die Frage ist "dumm" (bitte Anfürhungszeichen beachten), da auch die MSDN eine Antwort liefern würde.
  • Ja, ne extra Liste ist blösinn.

Lösung:


chatter.Sort(delegate(Chatter c1, Chatter c2){return string.Compare((c1==null?null:c1.Nick),(c2==null?null:c2.Nick));});

Grüße
Juy Juka

B
bluedragon Themenstarter:in
101 Beiträge seit 2008
vor 14 Jahren

Wow ich muss sagen ich bin wieder überwältigt !
Die Lösung ist sowohl kurz als auch funktionell.
Ich würde nur gerne verstehen wie sie funktioniert. Denn mit dem was da steht weiß ich leider nicht viel anzufangen 😦
Ich für mich persönlich finde es doof eine Lösung einfach nur hinzunehmen, da ich ja hier bin um auch zu lernen und nicht nur für Copy&Paste 😃

Verweise auf andere Webseiten sind natürlich auch von Hilfe, wenn es nicht zuviel Mühe macht .

lG blue

Man muss viel gelernt haben, um nach etwas, worüber man nicht Bescheid weiß, richtig fragen zu können.

Wenn du jemandem vertrauen kannst, erübrigt sich ein Vertrag. Kannst du ihm nicht vertrauen, ist ein Vertrag nutzlos.

5.941 Beiträge seit 2005
vor 14 Jahren

Hallo bluedragon

Es geht noch kürzer:


chatter.Sort((c1, c2) => string.Compare((c1==null?null:c1.Nick),(c2==null?null:c2.Nick)));

Wenn du verstehen willst, wie das funktioniert such am besten nach den schon erwähnten Stichworten. Also IComparer<T>, IComparable<T> und zusätzlich: Anonyme Methoden, Delegates, Lambda.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

B
bluedragon Themenstarter:in
101 Beiträge seit 2008
vor 14 Jahren

Danke für eure Hilfen, muss aber ehrlich sagen das ich eure beiden Lösungen immernoch nicht verstehe, mir nun aber selber helfen konnte durch eure Stichwörter. Ich habe mir die schöne Literatur von MSDN zu dem Thema IComparable<T>-Schnittstelle einverleibt und konnte sie danach problemlos auf mein Vorhaben projezieren und mein Problem lösen 😃

Falls jemand später ein änliches Problem hat, hier mal mein Code:

Hier die Klasse "Chatter":



    class Chatter : IComparable<Chatter>
    {
        #region Eigenschaften/Klassenvariablen


        private string pNick = "";
        public string Nick
        {
            get { return pNick; }
            set { pNick = value; }
        }

       //Noch ein paar diverse andere Eigenschaften, die für die Lösung
       //unerheblich sind, habe ich rausgenommen, um es knapp zu halten


        #endregion


        #region Methoden


        public int CompareTo(Chatter chatComparer)
        {
            return pNick.CompareTo(chatComparer.pNick);
        }


        #endregion
    }

Hier die Art und Weise wie man dann ganz leicht sortieren kann:



//habe jetzt mal meinen 2. Code nicht gepastet und eben
//ein kürzeres, aber eben so effektives, Beispiel genommen

//tuen wir jetzt mal so als hätte eine Listbox keine eigene Sortiermöglichkeit

public void ListeSortieren(object sender, EventArgs e)
{
    List<Chatter> chatter = new List<Chatter>(); 
   
    foreach(string nicks in listBox1.Items)
    {
        Chatter chatTemp = new Chatter();
        chatTemp.Nick = nicks;
        chatter.Add(chatTemp);
    }

    chatter.Sort(); //hier wäre vorher eine Exception gekommen, weil es keine Sortiermerkmal ausser "Default" gab

    listBox1.Items.Clear();

    foreach(Chatter chatTemp in chatter)
    {
        listBox1.Items.Add(chatTemp.Nick);
    }

    //nun ist die Liste sortiert
}

Der 2. Codesnippet ist vielleicht unnötig, jedoch wollte ich damit nur nochmal zeigen, dass man dann nichts Weiteres mehr zu machen brauch als die normale Methode "Sort()" aufzurufen, ohne jegliche Parameter.

Danke nochmal für eure Denkanstöße und bis zum nächsten Mal.

lG bluedragon 😃

Man muss viel gelernt haben, um nach etwas, worüber man nicht Bescheid weiß, richtig fragen zu können.

Wenn du jemandem vertrauen kannst, erübrigt sich ein Vertrag. Kannst du ihm nicht vertrauen, ist ein Vertrag nutzlos.

5.941 Beiträge seit 2005
vor 14 Jahren

Hallo bluedragon

Wenn du Anonyme Methoden verstanden hast, werden dir die anderen zwei Lösungen auch klar.

Du hast die Vergleichslogik für die Sortierung in der Klasse geschrieben, die Sortiert werden soll.
In unseren Beispielen steht die Vergleichslogik für die Sortierung irgendwo im Code.
Die Vergleichsfunktion wird sozusagen in die Liste eingespiesen und darin dann aufgerufen.

Das hat bspw. Vorteile wenn du einmal nach verschiedenen Eigenschaften sortieren möchtest, also die Sortierung dynamisch austauschen willst.
Geht alledings auch mit einer Klasse die IComparer implementiert, dort ist die Logik einfach in einer Klasse gekapselt die du dann als Parameter an der Sort-Methode übergibtst.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

2.187 Beiträge seit 2005
vor 14 Jahren

Hallo bluedragon,

dann erklär ich es mal, aber nur weil ich gute Laune habe 😁 :


[CSHARP](c1==null?null:c1.Nick)[/CSHARP]
Der Teil ist schnell erklärt (und kommt auch noch zwei mal vor): Ich nehme einfach den Nick von einerm Chatter-Objekt (c1 oder c2) falls dieses nicht [color]null[/color] ist ansonsten [color]null[/color].
Also bleibt von der Sortierung noch folgendes übrig:
[CSHARP]chatter.Sort(delegate(Chatter c1, Chatter c2){return string.Compare([Nick von c1],[Nick von c2]);}); [/CSHARP]


[CSHARP]string.Compare(...)[/CSHARP]
Das kann man sogar in der MSDN nachlesen, die Methode ermittelt einfach nur den Unterschied zwischen zwei [color]string[/color]-Objekten und giebt diesen (als Zahlenwert) zurück.
Also bleibt von der Sortierung noch folgendes übrig:
[CSHARP]chatter.Sort(delegate(Chatter c1, Chatter c2){return [Unterschied zwischen Nick von c1 und c2 als Zahl];}); [/CSHARP]


[CSHARP]delegate(Chatter c1, Chatter c2){...}[/CSHARP]
Dies ist ein Anonymer Delegat, als eine ganz normale Methode, die man auch so hätte schreiben können:
[CSHARP]public static decimal Compare(Chatter c1, Chatter c2)
{...}[/CSHARP]
Also bleibt von der Sortierung noch folgendes übrig:
[CSHARP]chatter.Sort(Compare);[/CSHARP]


[CSHARP]chatter.Sort(...)[/CSHARP]
Das kann man jetzt wirklich in der MSDN schauen. Im Endefeckt sortiert es, mit hilfe der Compare-Methode.

Gruß
Juy Juka

B
bluedragon Themenstarter:in
101 Beiträge seit 2008
vor 14 Jahren

Ich muss erneut über die Hilfsbereitschaft stauen , die ihr hier wie immer an den Tag legt.Ein erneutes Danke sehr !

Nun fällt es mir wesentlich leichter zu verstehen was das ganze bedeutet und wie es funktioniert. Bzw. es ist mir überhaupt möglich zu verstehen was in dieser Zeile passiert.
Als ich mit C# begann hab ich mir das Buch "C# .NET mit Methode" von Heinrich Rottmann mehrmals durchgelesen und nie wirklich den Part mit den Delegaten verstanden. Das einzige was sich bei mir in den Kopf "gebrannt" hat, war zu diesem Thema das Stichwort "Prototyp" und desshalb ist mit euren beiden Lösungen die ganze Zeit bei mir im Kopf ein Zwiespalt enstanden, denn ich wusste nicht wie ich den möglichen Parameter "Comparison<Chatter> comparison" (den mir die Lib von MVS anzeigt) mit einem Prototyp in Verbindung bringen sollte 😦

Und ehrlich gesagt ist das lediglich die einzige Frage die ich noch habe, denn MSDN gibt darüber leider keinerlei Aufschluss. Warum funktioniert "das Ganze" ? Warum kann man eine Methode als Vergleichslogik an die Methode Sort() übergeben ?

Ich meine ich verstehe nun eure beiden Beispiele , bis auf die Tatsache das diese als Parameter an die Sort()-Methode übergeben werden können. Weil für mich ist es einfach nicht schlüssig, dass der Prototyp einer Methode mit einem Comparison<Chatter> - /IComparable<Chatter>-Objekt gleichziehen kann 😦

Tut mir auch Leid falls ich nerve und meine Frage für euch etwas elementares sind, aber ich möchte es gerne, wie vorhin schon erwähnt, verstehen und nicht einfach nur hinnehmen.
Und wie ebenfalls schon erwähnt gibt MSDN leider keinen Aufschluss darüber.

Es würde mich wirklich freuen, wenn sich noch einmal wer die Mühe gibt mir dieses partitielle Problem zu erklären 🙂

lG bluedragon

ps: bin wie immer für alle möglichen Verweise offen, die mir richtigen Aufschluss geben können 👍

Man muss viel gelernt haben, um nach etwas, worüber man nicht Bescheid weiß, richtig fragen zu können.

Wenn du jemandem vertrauen kannst, erübrigt sich ein Vertrag. Kannst du ihm nicht vertrauen, ist ein Vertrag nutzlos.

5.941 Beiträge seit 2005
vor 14 Jahren

Hallo bluedragon

Was meinst du mit "Prototyp"?
Ich kenne das von Javascript her als einen Programmieransatz, sowas gibt es in .NET jedoch nicht.

Du machst im Prinzip nichts anderes als eine Referenz auf eine Methode, also ein Funktionszeiger (Delegate) an eine Methode zu übergeben.
Die Sort Methode kann dann selber diese Methode aufrufen und das Ergebnis auswerten.

Am besten liest du dich mal in Richtung Delegates ein.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

B
bluedragon Themenstarter:in
101 Beiträge seit 2008
vor 14 Jahren

Wenn ich mich Recht entsinne, dann meinte der Buchautor das in etwas so(kein Wortlaut oder Zitat, sondern eine sinngemäße Reflexion):
Ein Prototyp einer Methode (Delegate) ist nur eine temporäre Methode, die als solche nicht wirklich existiert sondern nur einer kurzen Funktion dient. Das Verlangen der Funktionsweise lässt es zu keine permanenten Methode notwendig zu machen.
Daher wird temporär ein Prototyp einer sonst exestierenden Methode erstellt, benutzt und wieder verworfen, da diese Methode nur diesen einen Moment einen Existenzgrund hat.

So in etwas würde ich 4-5 Seiten zusammenfassen.

Ich hoffe jetzt wird meine Frage aus dem letzten Beitrag klar 🙁

Wenn nicht hier nochmal in Kurzform: Was erlaubt es mir eine Delegate als Parameter an Sort() zu übergeben, wenn mir die Lib von MVS doch 4 ganz andere Konstruktoren preisgibt ?

lG bluedragon

Man muss viel gelernt haben, um nach etwas, worüber man nicht Bescheid weiß, richtig fragen zu können.

Wenn du jemandem vertrauen kannst, erübrigt sich ein Vertrag. Kannst du ihm nicht vertrauen, ist ein Vertrag nutzlos.

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo bluedragon,

Was erlaubt es mir eine Delegate als Parameter an Sort() zu übergeben, wenn mir die Lib von MVS doch 4 ganz andere Konstruktoren preisgibt ?

eine der Überladungen erwartet doch gerade einen Delegaten: List.Sort (Comparison<T>). Schau dir an, als was Comparison<T> definiert ist.

herbivore