在C#中使用char键的不区分大小写字典

Case Insensitive Dictionary with char key in C#

如果我有一个Dictionary,有没有可能使包含键的方法不区分大小写?

我知道,在Dictionary中使用了stringcomparer.invarialtcultureignorecase,但是当字典中的键是char类型时该怎么办?


Dictionary类有一个接受任何IEqualityComparer的构造函数。您需要做的是实现一个简单的不区分大小写的IEqualityComparer,并将其传递给构造函数,它将在评估密钥时使用。

这对于在不区分大小写的情况下实现IComparer是一个类似的问题。IEqualityComparer实际上是相同的:

  • 比较char忽略大小写的正确方法是什么?


您可以实现自己的比较器:

1
2
3
4
5
6
7
8
9
10
11
12
public class CharComparer : IEqualityComparer<char>
{
     public bool Equals(char c1, char c2)
     {
          return char.ToLowerInvariant(c1) == char.ToLowerInvariant(c2);
     }
     public int GetHashCode(char c1)
     {
          return char.ToLowerInvariant(c1).GetHashCode();
     }

}

并将其传递给构造函数:

1
var dict = new Dictioanry<char, object>(new CharComparer());


您也可以实现一个扩展方法:

1
2
3
4
public static bool ContainsKeyInsensitive(this Dictionary<char, ...> dict, char c)
{      
  return dict.ContainsKey(char.ToUpper(c)) || dict.ContainsKey(char.ToLower(c));
}


你也可以叫它两次。

1
2
3
4
if (dict.ContainsKey(char.ToLowerInvariant(ch)) || dict.ContainsKey(char.ToUpperInvariant(ch)))
{
    ...
}

作为一种扩展方法,它变成:

1
2
3
4
public static bool ContainsKeyInsensitive<T>(this Dictionary<char, T> dict, char ch)
{
    return dict.ContainsKey(char.ToLowerInvariant(ch)) || dictionary.ContainsKey(char.ToUpperInvariant(ch));
}

像这样定义字典:

1
Dictionary<string, int> Dict = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

起初,我知道公认的答案是有效的,这是一个很好的答案。然而,我发现不需要实现任何扩展方法/附加逻辑来实现期望的结果。

我想你使用字典是因为你想把一个键映射到一个特定的值——这正是它们的作用所在。如果您只使用它来查找密钥,那么应该使用HashSet

好吧,这么说吧,让我们来看看你对char的三个选择;

  • 您愿意映射大写和小写,使大写和小写都具有不同的值。
  • 您只愿意映射小写,这意味着大写与大写具有相同的值。
  • 您只愿意映射大写字母,这意味着小写字母的值与大写字母的值相同。

我会解释这三个问题。对于所有选项,考虑不知道输入字符是大写还是小写。

选项1;不同的键,不同的值。

这两种方法都要映射。如果需要'a''a'的不同值,则无论如何都需要添加它们。因此,您只需使用.ContainsKey(),它将返回所需的结果。此选项可能不适合您的需要,因为您正在查找不区分大小写的词典。

选项2:小写与大写具有相同的值。

如果您想随时获取小写值,只需调用.ContainsKey(yourChar.ToLower())

选项3:大写与小写具有相同的值。

同样的故事!现在,使用.ContainsKey(yourChar.ToUpper())得到正确的结果。因为你在评论中说你的字典只有大写字符,所以这应该是你的方法。

同样适用于不区分大小写的Dictionary;只需映射小写或大写(小写是我的首选,但这是您自己的选择)。

下面的代码片段应该演示它是如何工作的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Dictionary<char, object> dic = new Dictionary<char, object>();

public object GetIfKeyExists(char c)
{
    // Consider c = 'a' or c = 'A'

    // Option 1: Both have different values, so they should be existing anyway.
    if (dic.ContainsKey(c)) return dic[c];

    // Option 2: Only lowercase is mapped.
    char correctInput = c.ToLower();
    if (dic.ContainsKey(correctInput)) return dic[correctInput];

    // Option 3: Only uppercase is mapped.
    char correctInput = c.ToUpper();
    if (dic.ContainsKey(correctInput)) return dic[correctInput];
}

最后,我仍然想知道为什么你要检查上下。如果返回true,它会给出什么信息?你仍然不知道到底是哪一个存在——这就是为什么你应该选择映射大小写并坚持下去的原因。