欢迎光临

木子屋

标题: 从字符串中查找字符出现次数的方法和性能对比

作者: dnawo

日期: 2006-12-27 10:25 AM

分类: 脚本语言

内容: 今天在一场“特殊的讨论”中引入了一个问题，如何在C#求出字符串中某字符的出现次数，比如求“ADSFGEHERGASDF”中“A”出现的次数。首先想到的方法当然是从头遍历字符串并统计：
c1 = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == 'A')
{
c1++;
}
}
第二种方法也很容易想到，将字符串中所有要查找的字符去除，然后比较去除前后的字符串长度即可。这种方法遭到了某人的鄙视，据说性能很差而且多占空间。
c2 = str.Length - str.Replace("A", String.Empty).Length;
接下来某人又提出了第三种方法，是用要查找的字符为分隔符，将原字符串分隔为多个子串，然后求子串的数目即可。在C#中这是一个写起来很短的方法：
c3 = str.Split(new char[] { 'A' }).Length - 1;
我们从原理可以推断出三者性能的顺序，但究竟差距是多少呢，还是要动手试验一下。这是非常经典的测试代码：
string str = "SADTHDGSAFSDGTGHRDGSADFADDRHDFSGASDAA";
Stopwatch sw = new Stopwatch();
long t;
int c = 0;
GC.Collect();
Application.DoEvents();
sw.Start();
for (int i = 0; i < 100000; i++)
{
c = 三种算法
}
sw.Stop();
t = sw.ElapsedMilliseconds;
首先我们确保正确性，经测试三种方法都能正确处理多种情况，包括首尾、连续出现、不出现或串长度为0等，我所取的字符串是一个很普通的串。编译为Release版，预运行10次后获得以下结果：
遍历统计：13毫秒
替换后比较长度：112毫秒
断开字符串后计数：233毫秒
这里已经体现出差异，遍历统计比替换后比较要快10倍，断开字符串又要慢一些。接下来我又做了如下两个测试：
1、不改变字符串的长度，增加或减少要查找字符串的个数。
2、不改变要查找字符出现的频率，但增长字符串的长度。
结果发现，三种方法都随字符串长度增加线性变慢，而后两种方法还随要查找的字符增加而变慢。断开字符串的方法还受要查找字符串分布情况的影响。
研究Replace函数和Split函数的实现可以彻底解决这个问题。不过我没有心情细细研究了，我还是决定选用第二种方法——替换后比较长度。虽然其速度比第一种方法慢，但易于改写为求长度不为1的子串出现次数的方法。第一种方法若改为求长度大于1的字串就要考虑很多因素（尽管不一定真的很麻烦），我懒得想了，呵呵。

+ 查看当前日志评论 (1)

登录

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 0.722 ms

返回

标题: 从字符串中查找字符出现次数的方法和性能对比

你没有权限发表评论

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 0.722 ms

返回

暂无评论

返回

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 0.769 ms

返回