2009-06-24 9 views
1

Das nervt mich schon seit einiger Zeit. Ich habe mehrere Ansätze ausprobiert und keiner hat richtig funktioniert.Anpassen der Sortierreihenfolge von C# -Arrays

Ich schreibe und IRC-Client und versuche, die Liste der Benutzernamen (die nach Benutzerzugriffsebene im aktuellen Kanal sortiert werden müssen) zu sortieren.

Das ist einfach genug. Problem ist, dass diese Liste hinzugefügt werden muss, wenn ein Benutzer dem Kanal beitritt oder ihn verlässt, so dass sein Benutzername beim Verlassen der Liste entfernt und an der richtigen Stelle wieder hinzugefügt werden muss, wenn er sich wieder anmeldet.

Die Zugriffsebene jedes Benutzers wird durch ein einzelnes Zeichen am Anfang jedes Benutzernamens angegeben. Diese Zeichen sind reserviert, daher gibt es kein mögliches Problem eines Namens, der mit einem der Symbole beginnt. Die Symbole vom höchsten zum niedrigsten (in der Reihenfolge, ich brauche sie zu sortieren) sind: ~ & @ % +

Benutzer ohne jede Art von Zugriff haben kein Symbol vor ihrem Benutzernamen ein. Sie sollten am Ende der Liste stehen.

Zum Beispiel: der unsortierten Array folgenden enthalten könnte: ~ benutzer1 ~ user84 @ user3 & user8 + user39 user002 user2838% user29

und sortiert werden muss, um die Elemente in der folgenden Reihenfolge sind: ~ Benutzer1 ~ Benutzer84 & Benutzer8 @ Benutzer3% Benutzer29 + Benutzer39 Benutzer002 Benutzer2838

Nachdem Benutzer nach Zugriffsebene sortiert sind, müssen sie auch alphabetisch sortiert werden.

Fragen hier ist ein letzter Ausweg, wenn mir jemand helfen könnte, würde ich es sehr schätzen. Vielen Dank im Voraus.

+0

Wie speichern Sie die Liste der Benutzernamen? Wenn es sich um eine Datenbank handelt, könnten Sie dann SQL verwenden, um die Daten in der gewünschten Reihenfolge abzurufen, bevor Sie sie in eine Liste einfügen? – BarneyHDog

Antwort

1

Solange das Array ein Objekt enthält, implementieren Sie IComparable für das Objekt und rufen dann Array.Sort() auf.

Wenn die Sammlung änderbar ist, würde ich empfehlen, eine Liste <> zu verwenden.

+0

Wahrscheinlich am besten zu verwenden IComparable anstatt der nicht-generischen IComparable, oder erben aus Vergleichbare , die beide implementiert – thecoop

+0

Ja, IComparable wäre gut, wenn das OP eine Liste <> verwendet, aber ich glaube nicht, dass dies funktioniert für Array.Sort(), das IComparable erfordert. – stevehipwell

1

Sie können SortedList<K,V> mit der K (Schlüssel) Implementierung IComparable Schnittstelle verwenden, die dann die Kriterien Ihrer Art definiert. Das V kann einfach null oder dasselbe K-Objekt sein.

+0

Er würde aber nach den Werten sortieren wollen, nicht nach den Schlüsseln ... scheint ein sehr, sehr umständlicher Weg zu sein. –

+0

Nicht wirklich - Schlüssel == Werte in diesem Fall. Und wenn Sie bereits eine sortierte Liste haben, ist der Aufruf von Sort() jedes Mal, wenn Sie ein Element hinzufügen, ziemlich ineffizient. Wenn Sie eine sauberere Lösung wünschen, können Sie PowerCollections 'OrderedSet zum Beispiel verwenden (http://www.codeplex.com/PowerCollections). –

1

Sie können IComparer<T> oder Comparison<T>Array.Sort geben. Dann müssen Sie den Vergleich nur noch selbst durchführen. Wenn es ein relativ komplexer Vergleich ist (was so klingt), würde ich IComparer<T> in einer separaten Klasse implementieren, die Sie leicht Unit-Test können. Dann rufen:

Array.Sort(userNames, new UserNameComparer()); 

Sie könnten eine bequeme Instanz definiert haben wollen, wenn UserNameComparer keinen Staat hat:

Array.Sort(userNames, UserNameComparer.Instance); 

List<T> hat ähnliche Optionen für die Sortierung - ich würde persönlich eine Liste verwenden, anstatt eine Array, wenn Sie Artikel regelmäßig hinzufügen/entfernen.

Tatsächlich klingt es so, als ob Sie nicht oft eine vollständige Sortierung durchführen müssen. Das Entfernen eines Benutzers ändert die Sortierreihenfolge nicht und das Einfügen bedeutet nur das Einfügen an der richtigen Stelle.Mit anderen Worten, müssen Sie:

  • Liste erstellen und sortieren sie mit
  • Entfernen eines Benutzers starten nur eine einfache Bedienung ist
  • das Hinzufügen eines Benutzers erfordert herauszufinden, wo sie
einfügen

Sie können den letzten Schritt unter Verwendung von Array.BinarySearch oder List.BinarySearch ausführen, was Ihnen wiederum ermöglicht, eine benutzerdefinierte IComparer<T> anzugeben. Sobald Sie wissen, wo Sie den Benutzer einfügen können, können Sie dies relativ kostengünstig tun (im Vergleich zum erneuten Sortieren der gesamten Sammlung).

0

Sie sollten sich die Schnittstelle IComparer ansehen (oder es ist generic version). Überprüfen Sie bei der Implementierung der CompareTo-Methode, ob einer der beiden Benutzernamen eines Ihrer reservierten Zeichen enthält. Wenn keines von beiden ein spezielles reserviertes Zeichen hat oder beide das gleiche Zeichen haben, rufen Sie die Methode String.CompareTo auf, die die alphabetische Sortierung übernimmt. Andernfalls verwenden Sie Ihre benutzerdefinierte Sortierlogik.

0

gab ich die Sortierung einen Schuss und kam mit dem folgenden Sortier Ansatz bis:

List<char> levelChars = new List<char>(); 
levelChars.AddRange("+%@&~".ToCharArray()); 
List<string> names = new List<string>(); 
names.AddRange(new[]{"~user1", "~user84", "@user3", "&user8", "+user39", "user002", "user2838", "%user29"}); 
names.Sort((x,y) => 
       { 
        int xLevel = levelChars.IndexOf(x[0]); 
        int yLevel = levelChars.IndexOf(y[0]); 

        if (xLevel != yLevel) 
        { 
         // if xLevel is higher; x should come before y 
         return xLevel > yLevel ? -1 : 1; 
        } 

        // x and y have the same level; regular string comparison 
        // will do the job 
        return x.CompareTo(y);      
       }); 

Dieser Code Vergleich kann innerhalb der Compare Methode einer IComparer<T> Implementierung genauso gut leben.

Verwandte Themen