Eu tenho um aplicativo que usa dlls gerenciadas. Uma dessas DLLs retorna um dicionário genérico:
Dictionary<string, int> MyDictionary;
O dicionário contém teclas com maiúsculas e minúsculas.
Por outro lado, estou recebendo uma lista de chaves em potencial (string), mas não posso garantir o caso. Estou tentando obter o valor no dicionário usando as teclas. Mas é claro que o seguinte falhará, pois tenho uma incompatibilidade de casos:
bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );
Eu esperava que o TryGetValue tivesse um sinalizador de maiúsculas e minúsculas como mencionado no documento do MSDN , mas parece que isso não é válido para dicionários genéricos.
Existe uma maneira de obter o valor desse dicionário ignorando o caso principal? Existe uma solução melhor do que criar uma nova cópia do dicionário com o parâmetro StringComparer.OrdinalIgnoreCase apropriado ?
fonte
Respostas:
Não há como especificar a
StringComparer
no ponto em que você tenta obter um valor. Se você pensar sobre isso"foo".GetHashCode()
e"FOO".GetHashCode()
for totalmente diferente, não haverá uma maneira razoável de implementar uma obtenção que não diferencia maiúsculas de minúsculas em um mapa de hash que diferencia maiúsculas de minúsculas.No entanto, você pode criar um dicionário que não diferencia maiúsculas de minúsculas usando: -
Ou crie um novo dicionário que não diferencia maiúsculas de minúsculas com o conteúdo de um dicionário que diferencia maiúsculas de minúsculas existente (se tiver certeza de que não há colisão de maiúsculas e minúsculas): -
Este novo dicionário, em seguida, usa a
GetHashCode()
implementação noStringComparer.OrdinalIgnoreCase
modocomparer.GetHashCode("foo")
ecomparer.GetHashcode("FOO")
dar-lhe o mesmo valor.Como alternativa, se houver apenas alguns elementos no dicionário e / ou você precisar pesquisar apenas uma ou duas vezes, poderá tratar o dicionário original como um
IEnumerable<KeyValuePair<TKey, TValue>>
e apenas iterá-lo: -Ou, se preferir, sem o LINQ: -
Isso economiza o custo de criação de uma nova estrutura de dados, mas, em troca, o custo de uma pesquisa é O (n) em vez de O (1).
fonte
default(KeyValuePair<T, U>)
não énull
- é umKeyValuePair
ondeKey=default(T)
eValue=default(U)
. Portanto, você não pode usar o?.
operador no exemplo LINQ; você precisará pegarFirstOrDefault()
e, em seguida (neste caso específico), verificar seKey == null
.Para você, LINQers por aí que nunca usam um construtor de dicionário comum:
fonte
Não é muito elegante, mas caso você não possa alterar a criação do dicionário, e tudo o que você precisa é de um truque sujo, e quanto a isso:
fonte
ToUpperInvariant
vez deToLower
. 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)
? Além disso, você não obterá nulo para FirstOrDefault, pois keyvaluepair em C # é uma estrutura.