2008-10-02 15 views
5

Mam metodę, która pobiera IDictionary jako parametr. Teraz chcę podać metodę, która pobiera wartość z tego słownika, ale powinna być niezmienna.Konwertuj identyfikator <string, string> keys na małe litery (C#)

Więc moje rozwiązanie tego właśnie teraz miał mieć statyczną funkcję pętle za pomocą przycisków i konwertuje je tolower() tak:

private static IDictionary<ILanguage, IDictionary<string, string>> ConvertKeysToLowerCase(
    IDictionary<ILanguage, IDictionary<string, string>> dictionaries) 
{ 
    IDictionary<ILanguage, IDictionary<string, string>> resultingConvertedDictionaries 
     = new Dictionary<ILanguage, IDictionary<string, string>>(); 
    foreach(ILanguage keyLanguage in dictionaries.Keys) 
    { 
     IDictionary<string, string> convertedDictionatry = new Dictionary<string, string>(); 
     foreach(string key in dictionaries[keyLanguage].Keys) 
     { 
      convertedDictionatry.Add(key.ToLower(), dictionaries[keyLanguage][key]); 
     } 
     resultingConvertedDictionaries.Add(keyLanguage, convertedDictionatry); 
    } 
    return resultingConvertedDictionaries; 
} 

Teraz, to jest ok, ale nadal jest to dość ogromny fragment kodu, który zaprzecza mojej idei "czystej i wydajnej". Czy znasz jakieś alternatywy do tego, aby metoda .ContainsKey() w słowniku nie rozróżniała obudowy?

Odpowiedz

29

Tak - przekazywanie konstruktora słownika StringComparer.OrdinalIgnoreCase (lub innego porównywalnika ignorującego przypadki, w zależności od potrzeb w zakresie wrażliwości kultur).

Jon

+0

Dzięki! Udało się, ale wciąż muszę przejrzeć słownika ILanguage i ręcznie dodać słowniki . Nie mogę się tego pozbyć? – Tigraine

+0

Nie, że mogę od razu pomyśleć. To tylko jedna pętla ... prawie nieczytelna. Jeśli używasz .NET 3.5, możesz prawdopodobnie usprawnić to * trochę *, ale nie spociłbym się. Czy potrafisz zmienić twórcę oryginalnego słownika, aby w pierwszej kolejności określić porównawczy bez rozróżniania wielkości liter? –

+0

To wydaje się być najlepszym rozwiązaniem, ponieważ Tigraine chce osiągnąć porównanie polegające na ignorowaniu przypadków, a konwersja kluczy na małe litery jest tylko jedną (niepotrzebną) drogą do osiągnięcia tego celu. – VVS

0

Można użyć var słowo kluczowe, aby usunąć niektóre bałaganu. Technicznie źródło pozostaje takie samo. Również chciałbym po prostu przejść i wrócić słownika < ciąg, ciąg > bo nie robisz nic z tego parametru iLanguage i sprawiają, że metoda bardziej wielokrotnego użytku:

private static IDictionary<string, string> ConvertKeysToLowerCase(
    IDictionary<string, string> dictionaries) 
{ 
    var convertedDictionatry = new Dictionary<string, string>(); 
    foreach(string key in dictionaries.Keys) 
    { 
     convertedDictionatry.Add(key.ToLower(), dictionaries[key]); 
    } 
    return convertedDictionatry; 
} 

... i nazwać tak:

// myLanguageDictionaries is of type IDictionary<ILanguage, IDictionary<string, string>> 
foreach (var dictionary in myLanguageDictionaries.Keys) 
{ 
    myLanguageDictionaries[dictionary].Value = 
     ConvertKeysToLowerCase(myLanguageDictionaries[dictionary].Value); 
} 
+0

Dobrze, ale nadal nie rozwiązuje problemu z zapętleniem. Połączę twoje rozwiązanie z Jona Skeeta :) Dzięki! – Tigraine

+0

Cóż ... aby zmienić każdy element na liście, musisz dotknąć każdego elementu, który zawsze powoduje pętlę. Oczywiście możesz spróbować to w jakiś sposób zaciemnić;) – VVS

1

Możesz dziedziczyć po IDictionary samodzielnie i po prostu zlecać połączenia do wewnętrznej instancji Dictionary.

Add(string key, string value) { dictionary.Add(key.ToLowerInvariant(), value) ; } 
public string this[string key] 
{ 
    get { return dictionary[key.ToLowerInvariant()]; } 
    set { dictionary[key.ToLowerInvariant()] = value; } 
} 
// And so forth. 
-1

wersja LINQ przy użyciu metod IEnumerable<T> rozszerzenia:


     private static IDictionary<ILanguage, IDictionary<string, string>> ConvertKeysToLowerCase(
      IDictionary<ILanguage, IDictionary<string, string>> dictionaries) 
     { 
      return dictionaries.ToDictionary(
       x => x.Key, v => CloneWithComparer(v.Value, StringComparer.OrdinalIgnoreCase)); 
     } 

     static IDictionary<K, V> CloneWithComparer<K,V>(IDictionary<K, V> original, IEqualityComparer<K> comparer) 
     { 
      return original.ToDictionary(x => x.Key, x => x.Value, comparer); 
     } 
1

System.Collections.Specialized.StringDictionary() może pomóc. MSDN stwierdza:

„Kluczem jest obsługiwane w taki sposób, bez uwzględniania wielkości liter, jest tłumaczone na małe litery przed użyciem ze słownikiem strun

W .NET Framework w wersji 1.0, klasa ta wykorzystuje kulturę wrażliwych. Porównywanie ciągów znaków Jednak w programie .NET Framework w wersji 1.1 i nowszych ta klasa używa CultureInfo.InvariantCulture podczas porównywania łańcuchów.Aby uzyskać więcej informacji na temat wpływu kultury na porównywanie i sortowanie, zobacz Porównanie i sortowanie danych dla określonej kultury i Wykonywanie łańcucha niewrażliwych na kulturę Operacje. "

Powiązane problemy