如何计算C#字符串中字符或子串的出现次数:5种方法

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

字母"a"在单词"abracadabra"中出现多少次?用C#解决这个问题



想象一下:你在编写日志分析器、解析CSV文件,或者只是检查用户在电子邮件中输入@符号的次数。"统计字符或子字符串在字符串中出现的次数" 这个任务是那种在每个项目里都会出现的问题。在Stack Overflow上,这个问题已经积累了数千次浏览和几十种答案选项。这并不奇怪:在C#中至少有5种不同的方法,选择正确的方法可以节省数小时的调试时间。



在本文中,我们将分解所有流行的方法——从经典的循环到现代的Span<T>和LINQ。你将了解哪种方法更快,哪种更具可读性,哪种最好不要在生产中使用。开始吧!



1. 经典的foreach循环——老派方法



最直观的方式:获取一个字符串,遍历每个字符,并统计匹配项。它始终有效,并且不需要额外的库。



string text = "abracadabra";char target = 'a';int count = 0;

foreach (char c in text){ if (c == target) count++;}

Console.WriteLine($"字符'{target}'出现了{count}次。"); // 输出: 4


优点: 可读性强,过程可控,可以添加逻辑(例如,忽略大小写)。
缺点: 不适合统计子字符串(多个连续字符)——这需要编写嵌套循环。



2. LINQ中的Count()方法——针对字符的一行代码



如果你喜欢简洁的代码并且使用LINQ,那么这个选项适合你。Count()方法接受一个谓词,并返回满足条件的元素数量。



using System.Linq;

string text = "Hello, World!";char target = 'l';

int count = text.Count(c => c == target);Console.WriteLine(count); // 输出: 3


注意:Count()是来自System.Linq命名空间的扩展方法。如果你没有添加using System.Linq,代码将无法编译。



这个方法并不直接适用于统计子字符串。你需要先分割字符串或使用正则表达式(参见第5节)。



3. Span<T> 和 MemoryExtensions —— 最大性能



如果你处理大型字符串(兆字节级别的日志),并且每一毫秒都很重要,那么忘记LINQ吧。使用Span<char>和来自MemoryExtensions的Count()方法(从.NET 5+开始可用)。



using System;

string text = "abracadabra";ReadOnlySpan<char> span = text.AsSpan();int count = span.Count('a');

Console.WriteLine(count); // 输出: 4


为什么这么快? Span<T>处理连续内存块,无需分配新对象。MemoryExtensions中的Count()方法针对SIMD指令进行了优化——每个CPU周期可处理16-32个字符。



还有一个针对子字符串的解决方案:



int count = span.Count("ra"); // 统计子字符串 "ra" 出现的次数Console.WriteLine(count); // 输出: 2 ("abracadabra" 包含 "ra" 两次)


重要提示:此方法区分大小写。如果你需要忽略大小写,请先将字符串转换为统一大小写,或使用 span.Count("ra", StringComparison.OrdinalIgnoreCase)。



4. Split方法——针对子字符串的巧妙技巧



一个古老但有效的方法:按目标子字符串分割字符串,然后统计结果部分的数量减一。



string text = "one, two, three, one, four";string target = "one";

int count = text.Split(target, StringSplitOptions.None).Length - 1;Console.WriteLine(count); // 输出: 2


工作原理: Split

博客

书籍推荐