C# 通用字典的不区分大小写访问

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13230414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 07:49:59  来源:igfitidea点击:

Case insensitive access for generic dictionary

c#genericsdictionary

提问by TocToc

I have an application that use managed dlls. One of those dlls return a generic dictionary:

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

Dictionary<string, int> MyDictionary;  

The dictionary contains keys with upper and lower case.

字典包含大小写的键。

On another side I am getting a list of potential keys (string) however I cannot guarantee the case. I am trying to get the value in the dictionary using the keys. But of course the following will fail since I have a case mismatch:

另一方面,我得到了一个潜在键(字符串)列表,但我不能保证这种情况。我正在尝试使用键获取字典中的值。但当然,以下会失败,因为我有一个案例不匹配:

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

I was hoping the TryGetValue would have an ignore caseflag like mentioned in the MSDN doc, but it seems this is not valid for generic dictionaries.

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

Is there a way to get the value of that dictionary ignoring the key case? Is there a better workaround than creating a new copy of the dictionary with the proper StringComparer.OrdinalIgnoreCaseparameter?

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

采纳答案by Iain Galloway

There's no way to specify a StringComparerat the point where you try to get a value. If you think about it, "foo".GetHashCode()and "FOO".GetHashCode()are totally different so there's no reasonable way you could implement a case-insensitive get on a case-sensitive hash map.

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

You can, however, create a case-insensitive dictionary in the first place using:-

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

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

Or create a new case-insensitive dictionary with the contents of an existing case-sensitive dictionary (if you're sure there are no case collisions):-

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

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

This new dictionary then uses the GetHashCode()implementation on StringComparer.OrdinalIgnoreCaseso comparer.GetHashCode("foo")and comparer.GetHashcode("FOO")give you the same value.

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

Alternately, if there are only a few elements in the dictionary, and/or you only need to lookup once or twice, you can treat the original dictionary as an IEnumerable<KeyValuePair<TKey, TValue>>and just iterate over it:-

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

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

Or if you prefer, without the LINQ:-

或者,如果您愿意,也可以不使用 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;
  }
}

This saves you the cost of creating a new data structure, but in return the cost of a lookup is O(n) instead of O(1).

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

回答by Shoham

Its not very elegant but in case you cant change the creation of dictionary, and all you need is a dirty hack, how about this:

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

var item = MyDictionary.Where(x => x.Key.ToLower() == MyIndex.ToLower()).FirstOrDefault();
    if (item != null)
    {
        TheValue = item.Value;
    }

回答by Derpy

For you LINQers out there who never use a regular dictionary constructor:

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

myCollection.ToDictionary(x => x.PartNumber, x => x.PartDescription, StringComparer.OrdinalIgnoreCase)