SortedDictionary sortiert Sonderzeichen falsch

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 30 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    SortedDictionary sortiert Sonderzeichen falsch

    Hi,

    nach langem "tracen" hab ich jetzt endlich heraus gefunden, dass mein "SortedDictionary" das Sonderzeichen "~" falsch einsortiert. Hier mein Testcode:

    VB.NET-Quellcode

    1. Dim TabTest As New SortedDictionary(Of String, String)
    2. TabTest.Add("b", "01")
    3. TabTest.Add("a", "02")
    4. TabTest.Add("~", "03")
    5. TabTest.Add("c", "04")
    6. For k As Integer = 0 To TabTest.Count - 2
    7. If TabTest.Keys(k) < TabTest.Keys(k + 1) Then
    8. Debug.Print(TabTest.Keys(k) & "<" & TabTest.Keys(k + 1))
    9. ElseIf TabTest.Keys(k) > TabTest.Keys(k + 1) Then
    10. Debug.Print(TabTest.Keys(k) & ">" & TabTest.Keys(k + 1))
    11. Else
    12. Debug.Print(TabTest.Keys(k) & "=" & TabTest.Keys(k + 1))
    13. End If
    14. Next


    Damit erhalte ich das folgende Debug Listing:

    Quellcode

    1. ~>a
    2. a<b
    3. b<c


    Offensichtlich wird das Zeichen "~" ganz an den ANFANG gestellt, obwohl seinem Hexcode x'7E nach ganz ans ENDE gehört.

    Das ist leider fatal für meine Programmlogik, die auf eine aufsteigende Reihenfolge vertraut !

    Kann mir jemand sagen, wie ich das beheben kann?

    LG
    Peter
    @Peter329 Nimm mal Char und nicht String:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Dim TabTest As New SortedDictionary(Of Char, String)
    3. TabTest.Add("b"c, "01")
    4. TabTest.Add("a"c, "02")
    5. TabTest.Add("~"c, "03")
    6. TabTest.Add("c"c, "04")
    7. For k As Integer = 0 To TabTest.Count - 2
    8. If TabTest.Keys(k) < TabTest.Keys(k + 1) Then
    9. RichTextBox1.AppendText(TabTest.Keys(k) & "<" & TabTest.Keys(k + 1) & Environment.NewLine)
    10. ElseIf TabTest.Keys(k) > TabTest.Keys(k + 1) Then
    11. RichTextBox1.AppendText(TabTest.Keys(k) & ">" & TabTest.Keys(k + 1) & Environment.NewLine)
    12. Else
    13. RichTextBox1.AppendText(TabTest.Keys(k) & "=" & TabTest.Keys(k + 1) & Environment.NewLine)
    14. End If
    15. Next
    16. End Sub
    Bilder
    • Sorted.jpg

      5,23 kB, 132×149, 349 mal angesehen
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Danke erst mal an die beiden Ratgeber.

    Ich versuche jetzt mal den Vorschlag von RFG umzusetzen. Allerdings geht das so einfach nicht. Denn die Namen habe ich nur zu Testzwecken auf eine Stelle begrenzt! In der Realität sieht das dann eher so aus:

    VB.NET-Quellcode

    1. Dim TabTest As New SortedDictionary(Of String, String)
    2. TabTest.Add("baby", "01")
    3. TabTest.Add("abel", "02")
    4. TabTest.Add("~sue", "03")
    5. TabTest.Add("conny", "04")


    Und da klappt das natürlich nicht, wenn ich einfach ein SortedDictionary(Of Char, String) verwende. Das müsste dann wohl schon eher ein Array of Char() sein ... tja ... und dann geht das schon wieder los mit der Konvertiererei!

    VB.NET-Quellcode

    1. Dim TabTest As New SortedDictionary(Of Char(), String)
    2. TabTest.Add(CType("baby", Char()), "01")


    Das liefert mir die Fehlermeldung: Mindestens ein Objekt muss IComparable implementieren.

    Mhh ... wie mach ich das bloß?

    LG
    Peter

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

    Peter329 schrieb:

    In der Realität sieht das dann eher so aus:
    ;(
    Die meisten Software-Fehler liegen in der Spezifikation.
    Mit welcher Häufigkeit kommen solch Zeichen vor?
    Wie lang sind die Wörter?
    Mach ggf. eine Konvertierung ASCII to Byte, 8 Byte to Long und lass danach sortieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    ErfinderDesRades schrieb:

    komische Frage - ist doch bereits in post#2 beantwortet.


    Nö, isse nich !

    VB.NET-Quellcode

    1. Dim TabTest As New SortedDictionary(Of String, String)(StringComparer.CurrentCultureIgnoreCase)
    2. TabTest.Add("baby", "01")
    3. TabTest.Add("abel", "02")
    4. TabTest.Add("~sue", "03")
    5. TabTest.Add("conny", "04")


    IgnoreCase liefert exakt die gleiche Reihenfolge.

    Quellcode

    1. ~sue>abel
    2. abel<baby
    3. baby<conny


    Und damit ist mein Problem leider nicht gelöst.

    Allerdings bewerte ich alle Beiträge als hilfreich, wenn Leute so freundlich sind und versuchen mir einen Rat zu geben.

    LG
    Peter

    Peter329 schrieb:

    Und damit ist mein Problem leider nicht gelöst.
    Worin besteht Dein (Rest-) Problem?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Zitat RFG: Worin besteht Dein (Rest-) Problem?

    oh Mann ... mein klitzekleines Restproblem besteht darin die Einträge des SortedDirectory in die aufsteigende Reihenfolge gemäß des "<" Operators zu bringen.

    Die Namen stammen aus der Registry - die sind wild verstreut, bis zu 256 Stellen lang und es gibt ein paar 100.000 davon ... die will ich gegen einen vorangehenden Extrakt abgleichen ... und für einen Match-Merge ist nun mal eine fehlerfreie aufsteigende Reihenfolge essentiell.

    Jetzt kann ich das Ganze lösen, indem ich halt Kopfstände mache. Umgehen kann ich die Probleme allemal. Aber ich würde das gern "elegant" lösen ... na, vielleicht weiß ja doch jemand, wie man das hinbekommen kann.

    LG
    Peter

    P.S.:

    @EDR

    Zitat EDR: Naja, du musst auch den Konstruktor nehmen, auf den dort verlinkt ist.

    Das hab ich doch getan! Na, wahrscheinlich bin ich halt ein besonders dummes Exemplar und sehe das nicht. :) Trotzdem danke für den Hinweis.

    LG
    d.O.


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

    Peter329 schrieb:

    Aber ich würde das gern "elegant" lösen
    Poste mal ein paar Strings (~20), die sich anders verhalten, als Du es erwartest.
    Oder Kreiere eine "en-US"-Culture und sortiere nach der, weil Bill ist Amerikaner.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    xtts02 schrieb:

    deinen eigenen IComparer
    An dessen Inhalt tasten wir uns gerade heran. :/
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    xtts02 schrieb:

    Schreib' doch deinen eigenen IComparer (of T) und übergib' ihn an den Konstruktor (Siehe Posting #2).


    Also, wenn ich wüsste wie das geht, dann hätte ich das längst getan! :D

    Zitat RFG: Poste mal ein paar Strings (~20), die sich anders verhalten, als Du es erwartest.

    Ich will ja nicht Symptome kurieren. Sondern ich will eine VERLÄSSLICHE Reihenfolge erzeugen! Ich kann doch nicht wissen, welche Einträge übermorgen in der Registry enthalten sein werden. Die Reihenfolge muss exakt dem "<" Operator entsprechen. Im dümmsten Fall muss man da 256 Zeichen durchtesten.

    Zitat RFG: Oder Kreiere eine "en-US"-Culture und sortiere nach der, weil Bill ist Amerikaner.

    Und wie mache ich das? :o

    LG
    Peter

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

    Peter329 schrieb:

    Sondern ich will eine VERLÄSSLICHE Reihenfolge erzeugen!
    Was hindert Dich daran?
    Unsere Hilfe?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    So, da bin ich wieder ...

    ... mit einem Coding zum Abtesten der Sortierreihenfolge:

    VB.NET-Quellcode

    1. Dim TabTest As New SortedDictionary(Of String, String)
    2. 'Dim TabTest As New SortedDictionary(Of String, String)(StringComparer.CurrentCultureIgnoreCase)
    3. 'Dim TabTest As New SortedDictionary(Of String, String)(System.StringComparer.OrdinalIgnoreCase)
    4. Dim DupErr As Integer = 0
    5. Dim SeqErr As Integer = 0
    6. For i As Integer = 0 To 255
    7. Try
    8. TabTest.Add(Chr(i), CStr(i))
    9. Catch ex As Exception
    10. Debug.Print("Add: " & "x'" & CStr(i).PadLeft(5, " "c) & " - ERROR, duplicate")
    11. DupErr += 1
    12. End Try
    13. Next
    14. For k As Integer = 0 To TabTest.Count - 2
    15. If TabTest.Keys(k) < TabTest.Keys(k + 1) Then
    16. Debug.Print(("x'" & TabTest.Values(k)).PadLeft(5, " "c) _
    17. & " < " & ("x'" & TabTest.Values(k + 1)).PadLeft(5, " "c))
    18. ElseIf TabTest.Keys(k) > TabTest.Keys(k + 1) Then
    19. Debug.Print(("x'" & TabTest.Values(k)).PadLeft(5, " "c) _
    20. & " > " & ("x'" & TabTest.Values(k + 1)).PadLeft(5, " "c) & " ERROR")
    21. SeqErr += 1
    22. Else
    23. 'never executed - no duplicates in SortedDictionary
    24. End If
    25. Next
    26. Debug.Print("Sequence errors: " & CStr(SeqErr) _
    27. & " Duplicate errors: " & CStr(DupErr) _
    28. & " Total errors: " & CStr(SeqErr + DupErr))


    Hier das Ergebnis:

    Quellcode

    1. Add: x' 136 - ERROR, duplicate
    2. Add: x' 173 - ERROR, duplicate
    3. x'0 < x'1
    4. x'1 < x'2
    5. x'2 < x'3
    6. x'3 < x'4
    7. x'4 < x'5
    8. x'5 < x'6
    9. x'6 < x'7
    10. x'7 < x'8
    11. x'8 < x'14
    12. x'14 < x'15
    13. x'15 < x'16
    14. x'16 < x'17
    15. x'17 < x'18
    16. x'18 < x'19
    17. x'19 < x'20
    18. x'20 < x'21
    19. x'21 < x'22
    20. x'22 < x'23
    21. x'23 < x'24
    22. x'24 < x'25
    23. x'25 < x'26
    24. x'26 < x'27
    25. x'27 < x'28
    26. x'28 < x'29
    27. x'29 < x'30
    28. x'30 < x'31
    29. x'31 < x'127
    30. x'127 > x'39 ERROR
    31. x'39 < x'45
    32. x'45 < x'150
    33. x'150 < x'151
    34. x'151 > x'32 ERROR
    35. x'32 < x'160
    36. x'160 > x'9 ERROR
    37. x'9 < x'10
    38. x'10 < x'11
    39. x'11 < x'12
    40. x'12 < x'13
    41. x'13 < x'33
    42. x'33 < x'34
    43. x'34 < x'35
    44. x'35 < x'36
    45. x'36 < x'37
    46. x'37 < x'38
    47. x'38 < x'40
    48. x'40 < x'41
    49. x'41 < x'42
    50. x'42 < x'44
    51. x'44 < x'46
    52. x'46 < x'47
    53. x'47 < x'58
    54. x'58 < x'59
    55. x'59 < x'63
    56. x'63 < x'64
    57. x'64 < x'91
    58. x'91 < x'92
    59. x'92 < x'93
    60. x'93 < x'94
    61. x'94 < x'95
    62. x'95 < x'96
    63. x'96 < x'123
    64. x'123 < x'124
    65. x'124 < x'125
    66. x'125 < x'126
    67. x'126 < x'161
    68. x'161 < x'166
    69. x'166 < x'168
    70. x'168 < x'175
    71. x'175 < x'180
    72. x'180 < x'184
    73. x'184 < x'191
    74. x'191 < x'152
    75. x'152 < x'145
    76. x'145 < x'146
    77. x'146 < x'130
    78. x'130 < x'147
    79. x'147 < x'148
    80. x'148 < x'132
    81. x'132 < x'139
    82. x'139 < x'155
    83. x'155 > x'162 ERROR
    84. x'162 < x'163
    85. x'163 < x'164
    86. x'164 < x'165
    87. x'165 < x'128
    88. x'128 > x'43 ERROR
    89. x'43 < x'60
    90. x'60 < x'61
    91. x'61 < x'62
    92. x'62 < x'177
    93. x'177 > x'171 ERROR
    94. x'171 < x'187
    95. x'187 < x'215
    96. x'215 < x'247
    97. x'247 > x'167 ERROR
    98. x'167 < x'169
    99. x'169 < x'172
    100. x'172 < x'174
    101. x'174 < x'176
    102. x'176 < x'181
    103. x'181 < x'182
    104. x'182 < x'183
    105. x'183 < x'133
    106. x'133 > x'134 ERROR
    107. x'134 < x'135
    108. x'135 < x'149
    109. x'149 < x'137
    110. x'137 > x'129 ERROR
    111. x'129 < x'141
    112. x'141 < x'143
    113. x'143 < x'144
    114. x'144 < x'157
    115. x'157 > x'48 ERROR
    116. x'48 < x'188
    117. x'188 < x'189
    118. x'189 < x'190
    119. x'190 > x'49 ERROR
    120. x'49 < x'185
    121. x'185 > x'50 ERROR
    122. x'50 < x'178
    123. x'178 > x'51 ERROR
    124. x'51 < x'179
    125. x'179 > x'52 ERROR
    126. x'52 < x'53
    127. x'53 < x'54
    128. x'54 < x'55
    129. x'55 < x'56
    130. x'56 < x'57
    131. x'57 < x'97
    132. x'97 > x'65 ERROR
    133. x'65 < x'170
    134. x'170 < x'225
    135. x'225 > x'193 ERROR
    136. x'193 < x'224
    137. x'224 > x'192 ERROR
    138. x'192 < x'226
    139. x'226 > x'194 ERROR
    140. x'194 < x'228
    141. x'228 > x'196 ERROR
    142. x'196 < x'227
    143. x'227 > x'195 ERROR
    144. x'195 < x'229
    145. x'229 > x'197 ERROR
    146. x'197 < x'230
    147. x'230 > x'198 ERROR
    148. x'198 > x'98 ERROR
    149. x'98 > x'66 ERROR
    150. x'66 < x'99
    151. x'99 > x'67 ERROR
    152. x'67 < x'231
    153. x'231 > x'199 ERROR
    154. x'199 > x'100 ERROR
    155. x'100 > x'68 ERROR
    156. x'68 < x'240
    157. x'240 > x'208 ERROR
    158. x'208 > x'101 ERROR
    159. x'101 > x'69 ERROR
    160. x'69 < x'233
    161. x'233 > x'201 ERROR
    162. x'201 < x'232
    163. x'232 > x'200 ERROR
    164. x'200 < x'234
    165. x'234 > x'202 ERROR
    166. x'202 < x'235
    167. x'235 > x'203 ERROR
    168. x'203 > x'102 ERROR
    169. x'102 > x'70 ERROR
    170. x'70 < x'131
    171. x'131 > x'103 ERROR
    172. x'103 > x'71 ERROR
    173. x'71 < x'104
    174. x'104 > x'72 ERROR
    175. x'72 < x'105
    176. x'105 > x'73 ERROR
    177. x'73 < x'237
    178. x'237 > x'205 ERROR
    179. x'205 < x'236
    180. x'236 > x'204 ERROR
    181. x'204 < x'238
    182. x'238 > x'206 ERROR
    183. x'206 < x'239
    184. x'239 > x'207 ERROR
    185. x'207 > x'106 ERROR
    186. x'106 > x'74 ERROR
    187. x'74 < x'107
    188. x'107 > x'75 ERROR
    189. x'75 < x'108
    190. x'108 > x'76 ERROR
    191. x'76 < x'109
    192. x'109 > x'77 ERROR
    193. x'77 < x'110
    194. x'110 > x'78 ERROR
    195. x'78 < x'241
    196. x'241 > x'209 ERROR
    197. x'209 > x'111 ERROR
    198. x'111 > x'79 ERROR
    199. x'79 < x'186
    200. x'186 < x'243
    201. x'243 > x'211 ERROR
    202. x'211 < x'242
    203. x'242 > x'210 ERROR
    204. x'210 < x'244
    205. x'244 > x'212 ERROR
    206. x'212 < x'246
    207. x'246 > x'214 ERROR
    208. x'214 < x'245
    209. x'245 > x'213 ERROR
    210. x'213 < x'248
    211. x'248 > x'216 ERROR
    212. x'216 < x'156
    213. x'156 > x'140 ERROR
    214. x'140 > x'112 ERROR
    215. x'112 > x'80 ERROR
    216. x'80 < x'113
    217. x'113 > x'81 ERROR
    218. x'81 < x'114
    219. x'114 > x'82 ERROR
    220. x'82 < x'115
    221. x'115 > x'83 ERROR
    222. x'83 < x'154
    223. x'154 > x'138 ERROR
    224. x'138 > x'223 ERROR
    225. x'223 > x'116 ERROR
    226. x'116 > x'84 ERROR
    227. x'84 < x'254
    228. x'254 > x'222 ERROR
    229. x'222 < x'153
    230. x'153 > x'117 ERROR
    231. x'117 > x'85 ERROR
    232. x'85 < x'250
    233. x'250 > x'218 ERROR
    234. x'218 < x'249
    235. x'249 > x'217 ERROR
    236. x'217 < x'251
    237. x'251 > x'219 ERROR
    238. x'219 < x'252
    239. x'252 > x'220 ERROR
    240. x'220 > x'118 ERROR
    241. x'118 > x'86 ERROR
    242. x'86 < x'119
    243. x'119 > x'87 ERROR
    244. x'87 < x'120
    245. x'120 > x'88 ERROR
    246. x'88 < x'121
    247. x'121 > x'89 ERROR
    248. x'89 < x'253
    249. x'253 > x'221 ERROR
    250. x'221 < x'255
    251. x'255 < x'159
    252. x'159 > x'122 ERROR
    253. x'122 > x'90 ERROR
    254. x'90 < x'158
    255. x'158 > x'142 ERROR
    256. Sequence errors: 86 Duplicate errors: 2 Total errors: 88


    Das klappt also nicht ... ist gibt 86 sequence errors und 2 duplicates ... also insgesamt 88 Fehler! Fatal für einen Match-Merge. :)

    Der nächste Test:

    Dim TabTest As New SortedDictionary(Of String, String)(StringComparer.CurrentCultureIgnoreCase)

    liefert:

    Sequence errors: 34 Duplicate errors: 62 Total errors: 96

    Und der Vorschlag von EDR:

    Dim TabTest As New SortedDictionary(Of String, String)(System.StringComparer.OrdinalIgnoreCase)

    liefert:

    Sequence errors: 0 Duplicate errors: 60 Total errors: 60

    Tja ... was mach ich jetzt bloß?

    LG
    Peter

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

    Peter329 schrieb:

    Tja ... was mach ich jetzt bloß?

    RodFromGermany schrieb:

    Poste mal ein paar Strings (~20), die sich anders verhalten, als Du es erwartest.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!