Dictionary lässt sich nicht sortieren

  • VB.NET
  • .NET (FX) 4.0

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von Gather.

    Dictionary lässt sich nicht sortieren

    Hallo liebe Community,
    ich arbeite an einem neuen Projekt, diesbezüglich möchte ich ein Dictionary nach den Werten sortieren.
    Gefunden habe ich folgendes:
    stackoverflow.com/questions/11…r-by-value-of-the-integer

    Implementieren wollte ich dies nun so:

    VB.NET-Quellcode

    1. Dim dictCircles = New Dictionary(Of GCircleChartData, Integer)()
    2. For Each d In Data
    3. Dim val As Integer = 0
    4. val = (Height - 2) * (d.Value - _Minimum) \ (_Maximum - _Minimum)
    5. dictCircles.Add(d, val)
    6. Next
    7. Dim sorted = From pair In dictCircles Order By pair.Value
    8. Dim sortedDictionary = sorted.ToDictionary(Function(p) p.Key, Function(p) p.Value)
    9. For i As Integer = Data.Count - 1 To 0 Step -1
    10. Dim val As Integer = 0
    11. val = sortedDictionary(Data(i))
    12. tbTest.text &= vbnewLine & val 'Testprozedur
    13. Next


    Mein Ergebnis ist jedoch nicht sortiert, z.B. 27, 106 , 13
    Eigentlich sollte dies doch, vom Größten zum niedrigsten sortiert sein.

    Habt ihr Lösungsansätze?
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    VB.NET-Quellcode

    1. For i As Integer = Data.Count - 1 To 0 Step -1

    Damit rufst Du die Daten im sortierten Dictonary wieder in der Reihenfole ab, wie die Daten in "Data" stehen und "Data" ist nicht sortiert

    Es muss heißen - beim kleinstem zum größten Value

    VB.NET-Quellcode

    1. For Each pair in SortedDictonary
    2. Dim val As Integer = 0
    3. val = sortedDictionary(pair.key)
    4. tbTest.text &= vbnewLine & val 'Testprozedur
    5. Next

    Vom größtem zum kleinsten Value habe ich aktuell ein Blockade beim Nachdenken, werde den Beitrag aber editieren, wenn ich darauf komme.

    Edit:

    Probier mal bitte folgendes:

    VB.NET-Quellcode

    1. For Each pair in SortedDictonary.Reverse
    2. Dim val As Integer = 0
    3. val = pair.value ' Edit: pair enthält ja schon value!
    4. tbTest.text &= vbnewLine & val 'Testprozedur
    5. Next

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „Thias“ ()

    An sich, sortiert er sie mit

    VB.NET-Quellcode

    1. For Each pair in SortedDictonary.Reverse
    2. Dim val As Integer = 0
    3. val = sortedDictionary(pair.key)
    4. tbTest.text &= vbnewLine & val 'Testprozedur
    5. Next


    ..Richtig. Ich brauche jedoch die For i as Integer Schleife um später aus Data die einzelnen Eigenschaften auszulesen.
    Grundsätzlich könnte ich diesbezüglich das Dictionary Benutzen, geht aber eher schlecht wenn 2 gleiche Werte gegeben sind.

    edit://
    z.B.
    g.FillEllipse(New SolidBrush(Data(i).FillColor), New Rectangle(p, New Size(val, val)))
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Verstehe ich aktuell nicht:

    pair.key ist doch gleich d und somit vom Typ GCircleChartData - somit gleich Deinen Data(i)

    Was benötigst Du noch?

    pair.key muss doch zudem eindeutig sein - weil Schlüssel.

    Also: g.FillEllipse(New SolidBrush(pair.key.FillColor), New Rectangle(p, New Size(val, val)))

    Der @ErfinderDesRades würde sagen: Neue Aufgabenstellung!

    Edit:

    zur Not - wenn ich es nicht richtig begriffen haben sollte - ein zweites Dictonary machen:

    VB.NET-Quellcode

    1. dictCircles.Add(d, val)
    2. dictIndex.Add(d, i)


    Dann kannst Du Dir Dein "i" jederzeit über den Key wieder holen und mit Data(i) arbeiten

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Thias“ ()

    jo, ausserdem würd ich sagen, dass ein Dictionary eben eine Auflistung ist, die nicht zum Sortieren vorgesehen ist.
    Und schon gar nicht, um mit For i durchgeschleift zu werden.

    Wenn du derlei brauchst, dann nimm eine List(Of KeyValuePair(of TKey, TValue))

    Oder guggemal, was ich grad im ObjectBrowser fund:
    System.Collections.Generic.SortedDictionary(Of TKey, TValue)
    (Aber das ist auch nicht mit For i zu durchlaufen - nur mit ForEach.)

    ErfinderDesRades schrieb:

    ausserdem würd ich sagen, dass ein Dictionary eben eine Auflistung ist, die nicht zum Sortieren vorgesehen ist
    Nicht nur das, Dictionary kann sogar ausdrücklich nicht sortiert werden:
    ​The order of the keys in the Dictionary<TKey, TValue>.KeyCollection is unspecified, but it is the same order as the associated values in the Dictionary<TKey, TValue>.ValueCollection returned by the Values property.
    Siehe: msdn.microsoft.com/de-de/library/yt2fy5zk(v=vs.110).aspx

    Wie bereits richtig angemerkt gibts für diesen Anwendungsfall speziell die Klasse SortedDictionary, allerdings ist diese weniger effizient als die Klasse Dictionary (O(log n) im Vergleich zu O(1)).

    petaod schrieb:

    Du kannst doch einen Comparer spezifizieren.
    Damit müsste es meiner Meinung nach auch möglich sein, nach Value zu sortieren.

    Bis eben hatte ich noch nie von "Comparer" gehört oder gelesen.

    Findet sich aber wie folgt im Forum beschrieben:

    SortedDictionary-comparer

    Erscheint mir allerdings mit Kanonen auf Spatzen geschossen - werde es aber mal studieren.

    Brauchen:

    1.) Naja - teste gefühlsmäßig am Tag 100 Dinge aus und verwerfe später 99 wieder und lerne halt dabei.

    Von daher ist noch die Frage ob später normales Dictionary, SortedDictionary oder eine Lösung mit List of und keypairs übrigbleibt oder diese Lösung von Dir: SortedDictionary-comparer

    Sofern ich ein ThresholdDictionary (was immer dies genau ist - Edit gefunden: ThresholdDictionary: Dictionary für Schwellwerte) benötige, dann werde ich auf Dich zu gegebener Zeit zurückkommen

    2.) Generell wäre ein SortedDictionary für mich z.B. hilfreich, wenn der Key aus Kundennummern (Integer) bestehen würde, aber die Kundennummern nicht in aufsteigender Reihenfolge, sondern wahllos, dem SortedDictionary hinzugefügt wurden.

    Bei "For Each Kundennummer In SortedKundenDict" ist es da halt schon gut, die Kundennummern in aufsteigender Reihenfolge zu lesen - also ein ganz simples Beispiel.

    3. Oder ich vergesse dies alles und lese all die Informationen aus einer oder mehreren DataTable(s)!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Thias“ ()

    ich tippe auf letzteres. Ich jdfs. hab ein SortedDic noch nie gebraucht.
    Aber wenn du gerne Sachen ausprobierst - guck mal mein Schwellwerte-Dictionary an: ThresholdDictionary: Dictionary für Schwellwerte - das braucht man schon gelegentlich.

    ach - viel hübscher ist das hier: DelegateConverter

    Da wirds zB wirklich eingesetzt, nicht nur Demo

    ErfinderDesRades schrieb:

    ich tippe auf letzteres.

    Ist halt die Frage - wenn ich denn mal soweit bin und auch Zeit habe, werde ich dann mal benchmarken ob der mehrmalige Zugriff auf die DataTable oder auf das gefüllte Dictionary schneller ist - einmal muss ich die Daten ja immer aus der Datenbak einlesen.

    Edit: DelegateConverter - auch hilfreich - auch wenn ich dies auf Anhieb nur vom optischen Eindruck her beurteilen kann.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Thias“ ()

    Mittm Benchmark-Fimmel musste aufpassen: Zu 95% ists nämlich vollkommen irrelevant.
    Ob das Fenster mitte sortierten Kunden nun in 0,0001s aufpoppt, oder ob es das 20-fache(!) braucht: 0,002s - den User interessiert das sowas von Bohne!

    Das fällt in die Kategorie "premature Optimization", und dazu gilt es 3 Regeln zu beachten: Rules Of Optimization
    In diesem Ausnahmefall - der mir vor Augen schwebt - denke ich könnte es darauf ankommen - ansonsten hast Du natürlich Recht! Die einfachste Lösung ist die Beste!

    Die meisten Programme auf den "IBM System i - AS400"-Kunden-Servern haben ihre Berechnung spätestens innerhalb 10 Sekunden erledigt.

    Es gibt aber ein Programm bei einem Kunden, das läuft 20 Minuten - Optimierung des Produktionsablaufes.

    Da wird eine Baumstruktur für die Daten verwendet -welche ich aber systembedingt (vernünftig) nur auf Datenbankebene abbilden kann.

    Dieses Programm will ich im Herbst - vorher habe ich dafür wahrscheinlich keinerlei Zeit - weil recht aufwendig - auf eine Baumstrukturlösung unter vb.net bringen.

    Und da dürfte es dann schon auf Zugriffszeiten drauf ankommen.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Thias“ ()

    jo, das klingt nach einem guten Grund.
    Kennst du übrigens List(Of T)-/T()-.BinarySearch()?
    Wenn man Daten sortiert vorhalten kann, erreicht man beim Suchen mit BinarySearch Zugriffszeiten von O(log(n)) - das ist sehr schnell.
    Dictionary ist noch schneller, aber BinarySearch kann IndexOf ohne Mehr-Aufwand ersetzen. Ist also keine Optimierung im engeren Sinne, sondern einfach sauberer.

    (unter Optimierung verstehe ich Verbesserung in einer Hinsicht, erkauft durch Verschlechterung in anderer. Eine kostenlose Verbesserung ist einfach nur sauber)
    Anyways. @Thias es hat funktioniert. Ich verstehe auch nicht wieso ich das gestern nicht hinbekommen habe, obwohl du mir eigentlich schon die komplette Lösung geliefert hast.
    Danke nochmals an alle!
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!