我想确保C#字符串不包含特定字符。
我正在使用string.IndexOfAny(char[])
,在我看来,Regex在此任务中会更慢。有没有更好的方法来实现这一目标?速度在我的应用中至关重要。
答案 0 :(得分:4)
快速对IndexOf
vs IndexOfAny
vs Regex
vs Hashset
进行基准测试。
500字lorem ipsum干草堆,有两个字符针。
在大海捞针处测试,一个在大海捞针中,不在大海捞针中。
private long TestIndexOf(string haystack, char[] needles)
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
int x = haystack.IndexOfAny(needles);
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
private long TestRegex(string haystack, char[] needles)
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
Regex regex = new Regex(string.Join("|", needles));
for (int i = 0; i < 1000000; i++)
{
Match m = regex.Match(haystack);
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
private long TestIndexOf(string haystack, char[] needles)
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
int x = haystack.IndexOf(needles[0]);
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
private long TestHashset(string haystack, char[] needles)
{
HashSet<char> specificChars = new HashSet<char>(needles.ToList());
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
bool notContainsSpecificChars = !haystack.Any(specificChars.Contains);
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
1,000,000次迭代的结果:
索引:28/2718/2711
任意指数:153/141/17561
正则表达式:1068/1102/92324
Hashset:939/891/111702
注意:
总体而言,regex
比indexofany
慢了10倍,具体取决于干草堆和针头尺寸。
答案 1 :(得分:2)
您可以使用这种简洁有效的LINQ查询:
HashSet<char> specificChars = new HashSet<char>{ 'a', 'b', 'c'};
bool notContainsSpecificChars = !"test".Any(specificChars.Contains); // true
我使用了HashSet<char>
,因为它对查找有效,不允许重复。
如果你有一个数组作为输入,你可以使用constructor从中创建一个HashSet
:
char[] chars = new[] { 'a', 'b', 'c', 'c' };
specificChars = new HashSet<char>(chars); // c is removed since it was a duplicate
没有HashSet
的另一种方法是使用Enumerable.Intersect
+ Enumerable.Any
:
bool notContainsSpecificChars = !"test".Intersect(chars).Any();
答案 2 :(得分:0)
如果你必须只找到一个字符,那么最好调用方法IndexOf(singleChar)或IndexOf(singleChar,startIndex,charCount)。
诅咒正则表达式会更加昂贵!
答案 3 :(得分:0)
String.IndexOfAny(char[])
在CLR中实现,String.IndexOf
使用extern调用,所以它们都非常快。要么比使用正则表达式要快得多。
IndexOf
是否优于IndexOfAny
取决于您期望检查的字符数。基于一些非常粗略的基准测试,看起来IndexOf
对于2个或更少的字符表现得更好(少量),但IndexOfAny
对3个或更多的表现更好。但差别很小 - 使用IndexOfAny
的优势可能会被分配字符数组的成本所淹没。