Mam aplikację korzystającą z zarządzanych bibliotek DLL. Jedna z tych bibliotek dll zwraca ogólny słownik:
Dictionary<string, int> MyDictionary;
Słownik zawiera klawisze z dużymi i małymi literami.
Z drugiej strony otrzymuję listę potencjalnych kluczy (ciągów), ale nie mogę zagwarantować sprawy. Próbuję uzyskać wartość w słowniku za pomocą klawiszy. Ale oczywiście nie powiedzie się, ponieważ mam niedopasowanie wielkości liter:
bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );
Miałem nadzieję, że TryGetValue będzie miał flagę ignorowania przypadków, jak wspomniano w dokumencie MSDN , ale wydaje się, że nie jest to poprawne w przypadku ogólnych słowników.
Czy istnieje sposób, aby uzyskać wartość tego słownika ignorując kluczową wielkość liter? Czy istnieje lepsze obejście niż tworzenie nowej kopii słownika z odpowiednim parametrem StringComparer.OrdinalIgnoreCase ?
źródło
Odpowiedzi:
Nie ma sposobu, aby określić
StringComparer
punkt, w którym próbujesz uzyskać wartość. Jeśli się nad tym zastanowić"foo".GetHashCode()
i"FOO".GetHashCode()
są zupełnie inni, nie ma rozsądnego sposobu na wprowadzenie rozróżniania wielkości liter na mapie mieszającej uwzględniającej wielkość liter.Możesz jednak przede wszystkim utworzyć słownik bez rozróżniania wielkości liter, używając:
Lub utwórz nowy słownik bez rozróżniania wielkości liter z zawartością istniejącego słownika z rozróżnianiem wielkości liter (jeśli masz pewność, że nie występują kolizje wielkości liter): -
Ten nowy słownik używa następnie
GetHashCode()
implementacjiStringComparer.OrdinalIgnoreCase
socomparer.GetHashCode("foo")
icomparer.GetHashcode("FOO")
daje tę samą wartość.Alternatywnie, jeśli w słowniku jest tylko kilka elementów i / lub potrzebujesz tylko raz lub dwa razy wyszukać, możesz traktować oryginalny słownik jako
IEnumerable<KeyValuePair<TKey, TValue>>
i po prostu iterować:Lub jeśli wolisz, bez LINQ: -
Oszczędza to kosztów tworzenia nowej struktury danych, ale w zamian kosztem wyszukiwania jest O (n) zamiast O (1).
źródło
default(KeyValuePair<T, U>)
nie jestnull
- toKeyValuePair
gdzieKey=default(T)
iValue=default(U)
. Nie można więc użyć?.
operatora w przykładzie LINQ; musisz złapać,FirstOrDefault()
a następnie (w tym konkretnym przypadku) sprawdzić, czyKey == null
.Dla was LINQers, którzy nigdy nie używają zwykłego konstruktora słownika:
źródło
Nie jest zbyt elegancki, ale na wypadek, gdybyś nie mógł zmienić tworzenia słownika, a wszystko, czego potrzebujesz, to brudny hack, co powiesz na to:
źródło
ToUpperInvariant
zamiastToLower
. 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)
? Ponadto nie otrzymasz null dla FirstOrDefault, ponieważ keyvaluepair w C # jest strukturą.