Ich habe eine Anwendung, die verwaltete DLLs verwendet. Eine dieser DLLs gibt ein generisches Wörterbuch zurück:
Dictionary<string, int> MyDictionary;
Das Wörterbuch enthält Schlüssel in Groß- und Kleinschreibung.
Auf einer anderen Seite erhalte ich eine Liste möglicher Schlüssel (Zeichenfolge), kann jedoch den Fall nicht garantieren. Ich versuche, den Wert im Wörterbuch mit den Schlüsseln zu erhalten. Aber natürlich wird Folgendes fehlschlagen, da ich eine Fallinkongruenz habe:
bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );
Ich hatte gehofft, dass TryGetValue ein Ignorier-Fall- Flag haben würde, wie im MSDN-Dokument erwähnt , aber es scheint, dass dies für generische Wörterbücher nicht gültig ist.
Gibt es eine Möglichkeit, den Wert dieses Wörterbuchs zu ermitteln, indem der Schlüsselfall ignoriert wird? Gibt es eine bessere Problemumgehung als das Erstellen einer neuen Kopie des Wörterbuchs mit dem richtigen Parameter StringComparer.OrdinalIgnoreCase ?
quelle
Antworten:
Es gibt keine Möglichkeit, a
StringComparer
an dem Punkt anzugeben, an dem Sie versuchen, einen Wert zu erhalten. Wenn Sie darüber nachdenken"foo".GetHashCode()
und"FOO".GetHashCode()
völlig anders sind, gibt es keine vernünftige Möglichkeit, einen auf Groß- und Kleinschreibung nicht berücksichtigten Zugriff auf eine Hash-Map mit Groß- und Kleinschreibung zu implementieren.Sie können jedoch zunächst ein Wörterbuch ohne Berücksichtigung der Groß- und Kleinschreibung erstellen, indem Sie:
Oder erstellen Sie ein neues Wörterbuch ohne Berücksichtigung der Groß- und Kleinschreibung mit dem Inhalt eines vorhandenen Wörterbuchs ohne Berücksichtigung der Groß- und Kleinschreibung (wenn Sie sicher sind, dass keine Kollisionen zwischen Groß- und Kleinschreibung vorliegen): -
Dieses neue Wörterbuch verwendet dann die
GetHashCode()
Implementierung aufStringComparer.OrdinalIgnoreCase
socomparer.GetHashCode("foo")
undcomparer.GetHashcode("FOO")
gibt Ihnen den gleichen Wert.Wenn das Wörterbuch nur wenige Elemente enthält und / oder Sie nur ein- oder zweimal nachschlagen müssen, können Sie das ursprüngliche Wörterbuch als
IEnumerable<KeyValuePair<TKey, TValue>>
und behandeln und es einfach durchlaufen: -Oder wenn Sie es vorziehen, ohne den LINQ: -
Dies erspart Ihnen die Kosten für die Erstellung einer neuen Datenstruktur. Im Gegenzug betragen die Kosten für eine Suche jedoch O (n) anstelle von O (1).
quelle
default(KeyValuePair<T, U>)
ist nichtnull
- es ist einKeyValuePair
woKey=default(T)
undValue=default(U)
. Sie können den?.
Operator im LINQ-Beispiel also nicht verwenden . Sie müssen greifenFirstOrDefault()
und dann (für diesen speziellen Fall) prüfen, obKey == null
.Für Sie LINQer da draußen, die niemals einen regulären Wörterbuchkonstruktor verwenden:
quelle
Es ist nicht sehr elegant, aber falls Sie die Erstellung des Wörterbuchs nicht ändern können und alles, was Sie brauchen, ist ein schmutziger Hack, wie wäre es damit:
quelle
ToUpperInvariant
anstelle vonToLower
. msdn.microsoft.com/en-us/library/dd465121%28v=vs.110%29.aspxvar item = MyDictionary.FirstOrDefault(x => x.Key.ToUpperInvariant() == keyValueToCheck.ToUpperInvariant());
dict.Keys.Contains("bla", appropriate comparer)
? Darüber hinaus erhalten Sie für FirstOrDefault keine Null, da das Schlüsselwertpaar in C # eine Struktur ist.