比较 string.tolower 的更好替代方法是什么?

MrJ*_*ami 3 .net c# .net-core

根据我过去的经验和 stackoverflow,我了解到 String.ToLower() 的性能很差。现在我遇到以下问题,当特定单词出现在巨大列表中时,我需要过滤掉或执行特定操作。

旧方法,我想修复:

if (input.Any(i => i.ToLower() == "alle" || i.ToLower() == "all" || i.ToLower() == "none") 
{
    // do something
}
Run Code Online (Sandbox Code Playgroud)

我正在考虑使用哈希集,但我质疑性能以及它如何处理区分大小写,我基本上不关心区分大小写。使用哈希集对我来说有意义吗?

我目前的建议作为解决方案:

var unwantedInputsSet = new HashSet<string> {"alle", "all", "none"};
if (input.Any(i => i => unwantedInputsSet.Contains(i))) 
{
    // do something
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的替代方案。您有什么想法如何更好地解决这个问题吗?

Gur*_*ron 8

您可以将比较器传递给HashSet,例如StringComparer.InvariantCultureIgnoreCase

var unwantedInputsSet = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) {"alle", "all", "none"};
if (input.Any(i => unwantedInputsSet.Contains(i))) 
{
    // do something
}
Run Code Online (Sandbox Code Playgroud)

或者,按照评论中的建议,使用模式匹配:

if (input.Any(i => i.ToLower() is "alle" or "all" or "none") 
{
    // do something
}
Run Code Online (Sandbox Code Playgroud)

编译器应该将其转换为与您的代码类似的代码(尽管ToLower应该调用一次)。

至于性能 - 它可能高度依赖于实际数据,您应该使用预期的数据集来测量它。对于小型搜索集,HashSet其性能可能比几种比较更差,例如:

var cmpr = StringComparison.InvariantCultureIgnoreCase;
if (input.Any(i => string.Equals(i, "alle", cmpr) || string.Equals(i, "all", cmpr) || string.Equals(i, "none", cmpr)))
{
    // do something
}
Run Code Online (Sandbox Code Playgroud)

对于此类基准测试,我建议查看BenchmarkDotNet