区分大小写的字典C#上不区分大小写的搜索

时间:2017-06-28 06:45:51

标签: c# dictionary case-sensitive case-insensitive

我有一个案例敏感字典,

 Dictionary<string, uint> itemNames = new Dictionary<string, uint>(StringComparer.Ordinal);

所以我可以在这本词典中使用区分大小写的键。

例如,我可以拥有以下键值对,

  1. {test,10}
  2. {TEST,20}
  3. {test1,30}
  4. {test2,40}
  5. ...

    当有人传递密钥时,我想要检索该值。检索应该是部分不区分大小写的,这意味着,如果匹配的是精确的大小写,则返回区分大小写的结果,如果区分大小写的密钥不存在则检索不区分大小写的键值。

    例如,将上述值插入字典

    如果用户将密钥传递为&#34; TEST&#34;我需要返回20。

    如果用户将密钥传递为&#34; TEST1&#34; ,找不到区分大小写的密钥,所以我需要返回30.

    如何在C#中实现这一目标?

2 个答案:

答案 0 :(得分:3)

您应首先使用TryGetValue检查是否有项目。如果没有,请选择第一个匹配项:

string key = "test1";
int val;
if (!itemNames.TryGetValue(key, out val))
{
    val = itemNames.FirstOrDefault
                    (k => string.Equals(k.Key, key, StringComparison.OrdinalIgnoreCase)
                    )?.Value ?? 0;
}

请注意此代码的性能。如果你有一个大字典,第一次尝试有很多错过,第二个(不区分大小写)字典会更好。

答案 1 :(得分:0)

  1. 两个单独的词典:性能方面,获得O(1)平均查找时间的唯一方法是使用两个词典,其中一个将使用默认比较器,另一个将使用默认比较器一个不区分大小写的。

  2. 两个单独的词典,第2部分:也许最正确的方法是:

    // map each string to single item
    Dictionary<string, int> CaseSensitive;
    
    // map each string to multiple items, case insensitive
    Dictionary<string, List<KeyValuePair<string, int>>> CaseInsensitive;
    

    甚至

    // map each string to single item
    Dictionary<string, int> CaseSensitive;
    
    // map each string to multiple items, case insensitive, with O(1) lookup time
    Dictionary<string, HashSet<KeyValuePair<string, int>>> CaseInsensitive;
    

    您的不区分大小写的搜索可以正确返回所有匹配项,而不仅仅是最近插入的匹配项。

  3. “hacky”自定义相等比较器:或者,您可以使用单个字典但是欺骗了一点并制作了一个“特殊”比较器,它将为案例返回相同的哈希码 - 不敏感(因此也区分大小写)匹配,但根据标志更改其Equals方法的工作方式。这会将testTEST放在同一个存储桶中。

    但这是我不会使用这些的唯一方法,因为比较器是可变的(乍一看可能不是很明显这是如何工作的,这是不寻常的),它可能会导致细微的错误(你总是需要记住在插入/删除之前将IsCaseSensitive设置为true,并且对于区分大小写的搜索可能性能稍差(因为更多项目将共享同一个存储区)。