Ich schreibe ein Programm, um eine Reihenfolge festzulegen, in der verschiedene Objekte im Bericht erscheinen. Die Sequenz ist die Y-Position (Zelle) in der Excel-Tabelle.
Ein Demo-Teil des Codes ist unten. Was ich erreichen möchte, ist eine Sammlung, mit der ich mehrere Objekte hinzufügen und eine sortierte Sammlung basierend auf der Reihenfolge erhalten kann
SortedList list = new SortedList();
Header h = new Header();
h.XPos = 1;
h.name = "Header_1";
list.Add(h.XPos, h);
h = new Header();
h.XPos = 1;
h.name = "Header_2";
list.Add(h.XPos, h);
Ich weiß, dass die SortedList dies nicht zulässt, und habe nach einer Alternative gesucht. Ich will nicht zu beseitigen , die Duplikate und bereits versucht List<KeyValuePair<int, object>>
.
Vielen Dank.
c#
.net
linq
collections
sortedlist
Mayur Kotlikar
quelle
quelle
List
?Antworten:
Verwenden Sie Ihren eigenen IComparer!
Wie bereits in einigen anderen Antworten angegeben, sollten Sie Ihre eigene Vergleichsklasse verwenden. Aus diesem Grund verwende ich eine generische IComparer-Klasse, die mit allem funktioniert, was IComparable implementiert:
Sie werden es verwenden, wenn Sie eine neue SortedList, SortedDictionary usw.:
Hier ist int der Schlüssel, der dupliziert werden kann.
quelle
SortedDictionary
. Es ermöglicht auch das Entfernen.Sie können List <> sicher verwenden. Die Liste verfügt über eine Sortiermethode, deren Überladung IComparer akzeptiert. Sie können Ihre eigene Sortierklasse als erstellen. Hier ist ein Beispiel:
quelle
Ich benutze folgendes:
Mein Testfall:
Die Ausgabe:
quelle
Das Problem ist, dass das Datenstrukturdesign nicht den Anforderungen entspricht: Es müssen mehrere Header für dasselbe XPos gespeichert werden. Daher
SortedList<XPos, value>
sollte nicht ein Wert vonHeader
, sondern ein Wert von habenList<Header>
. Es ist eine einfache und kleine Änderung, die jedoch alle Probleme löst und verhindert, dass neue Probleme wie bei anderen Lösungsvorschlägen entstehen (siehe Erklärung unten):Bitte beachten Sie, dass das Hinzufügen eines "lustigen" Schlüssels, wie das Hinzufügen einer Zufallszahl oder das Vorgeben, dass 2 XPos mit demselben Wert unterschiedlich sind, zu vielen anderen Problemen führt. Zum Beispiel wird es schwierig oder sogar unmöglich, einen bestimmten Header zu entfernen.
Beachten Sie auch, dass die Sortierleistung viel besser ist, wenn nur wenige
List<Header>
als alle sortiert werden müssenHeader
. Beispiel: Wenn es 100 XPos gibt und jeder 100 Header hat, müssen 10000Header
im Gegensatz zu 100 sortiert werdenList<Header>
.Natürlich hat auch diese Lösung einen Nachteil: Wenn es viele XPos mit nur 1 Header gibt, müssen so viele Listen erstellt werden, was einen gewissen Aufwand bedeutet.
quelle
Einfachste Lösung (im Vergleich zu allen oben genannten): Verwenden
SortedSet<T>
Sie diese Option, um eineIComparer<SortableKey>
Klasse zu akzeptieren , und implementieren Sie dann die Compare-Methode auf folgende Weise:quelle
Vielen dank für Deine Hilfe. Bei der Suche nach mehr habe ich diese Lösung gefunden. (Verfügbar in Stackoverflow.com in anderer Frage)
Zuerst habe ich eine Klasse erstellt, die meine Objekte für Klassen (Kopf- und Fußzeilen usw.) kapselt.
Diese Klasse soll also die Objekte halten, und PosX jedes Objekts wird als int-Position angegeben
Was ich schließlich bekomme, ist die sortierte "Sequenz" -Liste.
quelle
Haben Sie versucht
Lookup<TKey, TElement>
, dass doppelte Schlüssel http://msdn.microsoft.com/en-us/library/bb460184.aspx möglich sind?quelle
Lookup
Ich glaube , es gibt auch keinen öffentlichen Konstrukteur . Irgendein guter Weg, um das zu umgehen?ToLookup
auf jedem tunIEnumerable<T>
.Sie können die SortedList verwenden, Ihren Wert für den TKey und int (count) für den TValue verwenden.
Hier ein Beispiel: Eine Funktion, die die Buchstaben eines Wortes sortiert.
quelle
Diese Auflistungsklasse verwaltet Duplikate und fügt die Sortierreihenfolge für das Duplikat ein. Der Trick besteht darin, die Elemente beim Einfügen mit einem eindeutigen Wert zu versehen, um eine stabile Sortierreihenfolge aufrechtzuerhalten. Dann packen wir alles in eine ICollection-Oberfläche.
eine Testklasse
Die Tagging-Struktur
Der Lambda-Vergleichshelfer
quelle
Das Problem ist, dass Sie etwas als Schlüssel verwenden, das kein Schlüssel ist (weil es mehrmals vorkommt).
Wenn Sie also echte Koordinaten haben, sollten Sie diese möglicherweise
Point
als Schlüssel für Ihre SortedList verwenden.Oder Sie erstellen einen
List<List<Header>>
Index , in dem Ihr erster Listenindex die x-Position und der innere Listenindex die y-Position definiert (oder umgekehrt, wenn Sie möchten).quelle
Der Schlüssel (Wortspiel beabsichtigt) besteht darin, eine
IComparable
Klasse auf Basis zu erstellen , die Gleichheit und Hashing beibehält, aber niemals mit 0 verglichen wird, wenn sie nicht gleich ist. Dies kann durchgeführt werden und kann mit ein paar Boni erstellt werden - stabile Sortierung (dh Werte, die zuerst zur sortierten Liste hinzugefügt werden, behalten ihre Position bei) undToString()
können einfach den tatsächlichen Wert der Schlüsselzeichenfolge zurückgeben.Hier ist ein Strukturschlüssel, der den Trick machen sollte:
quelle
Linq.Lookup ist cool und alles, aber wenn Ihr Ziel darin besteht, einfach die "Schlüssel" zu durchlaufen , während sie dupliziert werden können, können Sie diese Struktur verwenden:
Dann können Sie schreiben:
HTH
quelle
Der Trick besteht darin, Ihr Objekt mit einem eindeutigen Schlüssel zu erweitern. Siehe den folgenden Test, der bestanden wird. Ich möchte meine Punkte nach ihrem X-Wert sortieren. Wenn Sie in meiner Vergleichsfunktion nur einen nackten Point2D verwenden, werden Punkte mit demselben X-Wert entfernt. Also verpacke ich den Point2D in eine Tagging-Klasse namens Indexed.
Dienstprogramme, um diese Arbeit zu machen, sind
Ein Vergleicher, der ein Lambda nimmt
Eine Tagging-Struktur
quelle
So habe ich das Problem gelöst. Es soll threadsicher sein, obwohl Sie das
lock
s einfach entfernen können, wenn Sie das nicht brauchen. Beachten Sie auch, dass ein beliebigerInsert
Index nicht unterstützt wird, da dies die Sortierbedingung verletzen könnte.quelle
Erstellen Sie eine Klasse und fragen Sie die Liste ab:
quelle
Hier ist meine Meinung dazu. Seien Sie sich bewusst, hier könnten Drachen sein, C # ist für mich noch ziemlich neu.
Verwendung:
quelle
Queue
In BCL gibt es bereits eine Klasse , die eine First-In- und First-Out-Sammlung von Elementen darstellt. Die Semantik Ihrer Klasse ist unterschiedlich. Ihre Klasse hat einen Anfang (wo Elemente aus der Warteschlange entfernt werden), aber kein Ende (ein Element kann überall eingefügt werden). DieEnqueue
Methode in Ihrer Klasse ist also meiner Meinung nach bedeutungslos.PriorityQueue
wäre passender Name.-2 * 5 == +10
) reparieren , es ist also keine große Sache. :-)