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

Toc*_*Toc 225 c# generics dictionary

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

Dictionary<string, int> MyDictionary;  
Run Code Online (Sandbox Code Playgroud)

字典包含大小写的键.

另一方面,我得到一个潜在的密钥列表(字符串),但我不能保证这种情况.我试图使用键获取字典中的值.但是,由于案件不匹配,以下情况当然会失败:

bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );  
Run Code Online (Sandbox Code Playgroud)

我希望TryGetValue会有一个像MSDN文档中提到的忽略大小写标志,但它似乎对通用词典无效.

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

Iai*_*way 460

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

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

var comparer = StringComparer.OrdinalIgnoreCase;
var caseInsensitiveDictionary = new Dictionary<string, int>(comparer);
Run Code Online (Sandbox Code Playgroud)

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

var oldDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var newDictionary = new Dictionary<string, int>(oldDictionary, comparer);
Run Code Online (Sandbox Code Playgroud)

这本新词典然后使用GetHashCode()上实现StringComparer.OrdinalIgnoreCase这样comparer.GetHashCode("foo")comparer.GetHashcode("FOO")给你同样的价值.

或者,如果字典中只有少数元素,和/或您只需要查找一次或两次,您可以将原始字典视为一个IEnumerable<KeyValuePair<TKey, TValue>>并且只是迭代它: -

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

或者如果你愿意,没有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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我已经使用.NET已经十年了,我现在只想出来了!为什么使用Ordinal而不是CurrentCulture? (2认同)

Der*_*rpy 31

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

myCollection.ToDictionary(x => x.PartNumber, x => x.PartDescription, StringComparer.OrdinalIgnoreCase)
Run Code Online (Sandbox Code Playgroud)

  • C# 还具有构造函数:“Dictionary(IDictionary&lt;TKey, TValue&gt;dictionary, IEqualityComparer&lt;TKey&gt;? Comparer);”,可让您使用新的比较器有效地重新创建相同的字典。 (2认同)

Sho*_*ham 8

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

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

  • 或者只是这样:new Dictionary <string,int>(otherDict,StringComparer.CurrentCultureIgnoreCase); (11认同)
  • 根据"在.NET Framework中使用字符串的最佳实践",使用"ToUpperInvariant"而不是"ToLower".https://msdn.microsoft.com/en-us/library/dd465121%28v=vs.110%29.aspx (4认同)
  • 为什么不只是`dict.Keys.Contains(“bla”,适当的比较器)`?此外,FirstOrDefault 不会为 null,因为 C# 中的键值对是一个结构体。 (3认同)

Maj*_*jor 5

有更简单的方法:

using System;
using System.Collections.Generic;
....
var caseInsensitiveDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
Run Code Online (Sandbox Code Playgroud)