324

我有一个使用托管 dll 的应用程序。其中一个 dll 返回一个通用字典:

Dictionary<string, int> MyDictionary;  

字典包含大小写的键。

另一方面,我得到了一个潜在键(字符串)的列表,但是我不能保证这种情况。我正在尝试使用键获取字典中的值。但是,由于我的大小写不匹配,以下内容当然会失败:

bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );  

我希望 TryGetValue 会有一个忽略大小写标志,就像MSDN doc中提到的那样,但这似乎对通用字典无效。

有没有办法在忽略关键情况的情况下获取该字典的值?有没有比使用正确的StringComparer.OrdinalIgnoreCase参数创建字典的新副本更好的解决方法?

4

4 回答 4

671

StringComparer在您尝试获取值的地方无法指定 a 。如果您考虑一下,"foo".GetHashCode()并且"FOO".GetHashCode()完全不同,那么没有合理的方法可以在区分大小写的哈希映射上实现不区分大小写的 get 。

但是,您可以首先使用以下方法创建不区分大小写的字典:-

var comparer = StringComparer.OrdinalIgnoreCase;
var caseInsensitiveDictionary = new Dictionary<string, int>(comparer);

或者使用现有区分大小写的字典的内容创建一个新的不区分大小写的字典(如果您确定没有大小写冲突):-

var oldDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var newDictionary = new Dictionary<string, int>(oldDictionary, comparer);

然后,这个新字典使用soGetHashCode()上的实现并为您提供相同的值。StringComparer.OrdinalIgnoreCasecomparer.GetHashCode("foo")comparer.GetHashcode("FOO")

或者,如果字典中只有几个元素,和/或您只需要查找一次或两次,则可以将原始字典视为 anIEnumerable<KeyValuePair<TKey, TValue>>并对其进行迭代:-

var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var value = myDictionary.FirstOrDefault(x => String.Equals(x.Key, myKey, comparer)).Value;

或者,如果您愿意,不使用 LINQ:-

var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
int? value;
foreach (var element in myDictionary)
{
  if (String.Equals(element.Key, myKey, comparer))
  {
    value = element.Value;
    break;
  }
}

这为您节省了创建新数据结构的成本,但作为回报,查找的成本是 O(n) 而不是 O(1)。

于 2012-11-05T10:44:26.450 回答
61

对于那些从不使用常规字典构造函数的 LINQers

myCollection.ToDictionary(x => x.PartNumber, x => x.PartDescription, StringComparer.OrdinalIgnoreCase)
于 2017-03-09T19:41:26.770 回答
13

有更简单的方法:

using System;
using System.Collections.Generic;
....
var caseInsensitiveDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
于 2020-09-28T13:40:34.140 回答
12

它不是很优雅,但如果你不能改变字典的创建,你所需要的只是一个肮脏的黑客,这个怎么样:

var item = MyDictionary.Where(x => x.Key.ToLower() == MyIndex.ToLower()).FirstOrDefault();
    if (item != null)
    {
        TheValue = item.Value;
    }
于 2014-12-03T08:58:09.723 回答