在 C# 中具有字符串键类型的不区分大小写字典

Posted

技术标签:

【中文标题】在 C# 中具有字符串键类型的不区分大小写字典【英文标题】:Case-INsensitive Dictionary with string key-type in C# 【发布时间】:2012-12-08 22:41:27 【问题描述】:

如果我有Dictionary<String,...>,是否可以使ContainsKey 之类的方法不区分大小写?

这似乎相关,但我没有正确理解它:c# Dictionary: making the Key case-insensitive through declarations

【问题讨论】:

Case insensitive access for generic dictionary的可能重复 这个问题是相关的,但与这个问题并不完全重复。那一个进入如何处理现有的字典。我从新代码开始,所以这里的答案更适合。 【参考方案1】:

这似乎相关,但我没有正确理解:c# Dictionary: making the Key case-insensitive through declarations

确实有关系。解决方案是告诉字典实例不要使用标准的字符串比较方法(区分大小写),而是使用不区分大小写的方法。这是使用appropriate constructor:

var dict = new Dictionary<string, YourClass>(
        StringComparer.InvariantCultureIgnoreCase);

构造函数需要一个IEqualityComparer,它告诉字典如何比较键。

StringComparer.InvariantCultureIgnoreCase 为您提供IEqualityComparer 实例,它以不区分大小写的方式比较字符串。

【讨论】:

可能,StringComparison.OrdinalIgnoreCase 比较器比基于文化的比较快:***.com/questions/492799/… @ShridharRKulkarni 你基本上不能(有效地)。比较逻辑是内部字典数据结构的核心部分。为此,容器必须为其数据维​​护多个索引,而字典不会这样做。【参考方案2】:
var myDic = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
myDic.Add("HeLlo", "hi");

if (myDic.ContainsKey("hello"))
    Console.WriteLine(myDic["hello"]);

【讨论】:

【参考方案3】:

很少有机会处理从第三方或外部 dll 提取的字典。使用 linq

YourDictionary.Any(i => i.KeyName.ToLower().Contains("yourstring")))

【讨论】:

这很好用。不过需要注意的是,如果您将Any 更改为SingleOrDefault,如果null 不存在,您将不会得到它,相反,您将获得一个键值对,键和值都设置为null!跨度> Contains 似乎是您当时正在做的事情的一个非常具体的用例。作为一个更通用的有用答案,我认为Equals 更好。同样的,与其用ToLower()复制一个字符串,不如使用StringComparison.xxxCase 我很想对此投反对票。请注意,如果您是字典的所有者,那么这肯定不是这样做的方法。如果您不知道字典是如何实例化的,请仅使用此方法。即使这样,对于字符串的精确匹配(不仅仅是部分匹配),使用dict.Keys.Contains("bla", appropriate comparer) LINQ 重载以方便使用。【参考方案4】:

如果您无法控制实例的创建,假设您的对象已从 json 等中删除,您可以创建一个继承自字典类的包装类。

public class CaseInSensitiveDictionary<TValue> : Dictionary<string, TValue>

    public CaseInSensitiveDictionary() : base(StringComparer.OrdinalIgnoreCase)

【讨论】:

如何在保持 Dictionary 语法的情况下做到这一点?【参考方案5】:

我刚刚遇到了同样的麻烦,我需要在 ASP.NET Core 控制器中使用不区分大小写的字典。

我写了一个可以解决问题的扩展方法。 也许这对其他人也有帮助......

public static IDictionary<string, TValue> ConvertToCaseInSensitive<TValue>(this IDictionary<string, TValue> dictionary)

    var resultDictionary = new Dictionary<string, TValue>(StringComparer.InvariantCultureIgnoreCase);
    foreach (var (key, value) in dictionary)
    
        resultDictionary.Add(key, value);
    

    dictionary = resultDictionary;
    return dictionary;

使用扩展方法:

myDictionary.ConvertToCaseInSensitive();

然后从字典中获取一个值:

myDictionary.ContainsKey("TheKeyWhichIsNotCaseSensitiveAnymore!");

【讨论】:

【参考方案6】:

我知道这是一个较老的问题,但我遇到了同样的问题,即字典来自未在构造函数中实现忽略大小写 StringComparer 的第 3 方工具。从上面的 @Soviut 方法调整而来,但感觉这更干净,让您可以立即使用该值。

var lookup = source.FirstOrDefault(x => x.Key.Equals("...", StringComparison.OrdinalIgnoreCase));
if (lookup.Key != null)

【讨论】:

以上是关于在 C# 中具有字符串键类型的不区分大小写字典的主要内容,如果未能解决你的问题,请参考以下文章

re.sub() 的不区分大小写的正则表达式模式问题[重复]

接受所有数据类型的不区分大小写的 C++ 排序?

nvarchar 类型的不区分大小写的主键,其中 ß != ss

C ++ 11字符串开头的不区分大小写的比较(unicode)

字符串与 Java 枚举的不区分大小写匹配

字符串的字典比较[不区分大小写]