String.Split和Regex.Split有什么区别?

16
如果我有一个带基本分隔符(例如|)的分隔文本文件,使用StringRegex拆分是否有区别?在性能方面,一个与另一个相比是否会有更好的表现?
我假设如果您有需要转义的分隔符(例如\|),则应使用Regex.Split进行拆分。
除了这个原因,还有其他使用Regex.Split而不是String.Split的原因吗?

1
如果速度很重要,那就对这两个选项进行基准测试。我预计 String.Split 会更快,但除非你处理大量数据,否则这不太重要。 - Will A
4个回答

14

Regex.Split更加强大,但对于仅使用字符串中不存在的字符进行基本分隔的情况,String.Split函数更易于处理。

就性能而言,您需要创建一个测试并试用它。 但是,除非您知道此功能将成为某个重要过程的瓶颈,否则不要预先优化。


值得将统计数据合并为一个答案。 - PAS

9
似乎在简单情况下,使用string.Split()更加有效。我在Benchmark .NET中进行了测试。

测试环境为.NetCore 2.2.6:


方法 平均值 误差 标准偏差 中位数
RegexSplit 486.47 ns 9.769 ns 24.15 ns 481.72 ns
Split 84.76 ns 4.503 ns 13.21 ns 81.12 ns

测试环境为.Net 5.0.101:


方法 平均值 误差 标准偏差
RegexSplit 182.10 ns 2.091 ns 1.956 ns
Split 50.29 ns 0.709 ns 0.663 ns

注意:测试时硬件不同,因此版本间相对性能的差异比绝对性能的差异更重要。

测试内容:

public class RegexVsSplit
{
    private readonly string data = "host:7000";

    public RegexVsSplit()
    {
    }

    [Benchmark]
    public string[] RegexSplit() => Regex.Split(data, ":");

    [Benchmark]
    public string[] Split() => data.Split(':');
}

3
注意:对于未来的读者,请注意,新的.Net Core / .NET 5.0预览版6已经改善了正则表达式(以及许多其他领域)的性能,因此最好像@Tjaart一样进行另一个基准测试。 - Reza
谢谢你的建议。我重新运行了测试,发现有很大的差异,但是 string.Split 似乎仍然是最优选择。 - Tjaart
1
可能需要进行另一个测试,因为每次重新编译正则表达式。 还应该使用以下内容进行测试: private static readonly Regex colonRegex = new Regex(@":", RegexOptions.Compiled); - Chris Welton

6
默认情况下,如果您没有一些复杂的要求需要使用正则表达式来处理,我会使用String.Split。当然,正如其他人所提到的,根据您的需求进行性能分析。一定要使用RegexOptions.Compiled进行分析,并了解其工作原理。查看To Compile or Not To CompileHow does RegexOptions.Compiled work?以及搜索其他相关文章。 String.Split 的一个好处是它的StringSplitOptions.RemoveEmptyEntries,用于在分隔符之间不存在数据时删除空结果。使用相同分隔字符串/字符的正则表达式模式将具有多余的空条目。这只是小问题,可以通过简单的LINQ查询来过滤掉String.Empty结果来解决。
话虽如此,如果您需要包含分隔符,则使用正则表达式非常容易。这可以通过在模式周围添加括号()来实现捕获组。例如:
string input = "a|b|c|d|e|f";
foreach (var s in Regex.Split(input, @"\|"))
    Console.WriteLine(s);

Console.WriteLine("Include delimiter...");
// notice () around pattern
foreach (var s in Regex.Split(input, @"(\|)"))
    Console.WriteLine(s);

您可能也会发现这个问题有帮助:如何使用.NET按字符串拆分字符串并包含分隔符?


1
  1. 对于简单的分隔符,应该使用String.Split,例如逗号分隔的电子邮件地址。
  2. 对于复杂的分隔符(使用正则表达式),例如如果您在引号中有分隔符,则不应该被分隔开。 A,B = 两个标记,A和B "A,B" = 一个标记,忽略引号内的逗号
  3. 按照Ahmad的建议包括分隔符

哪种方法更快,这是非常主观的。正则表达式在执行时会更快,但是正则表达式的编译时间和设置时间在实例创建时会更长。但是,如果您在开始时准备好您的正则表达式对象,并重用同一正则表达式进行拆分,速度将更快。

String.Split不需要任何设置时间,但它是纯顺序搜索操作,对于大文本,它的工作速度会较慢。


Akash Kava,在什么情况下,Regex.Split比String.Split更快?正则表达式如何可能比O(n)更快地分割字符串?(为什么我不能用'@'符号引用你的名字?) - agentnega
正则表达式应该使用DFA(确定有限状态自动机)http://en.m.wikipedia.org/wiki/Deterministic_finite_automaton,这比多个顺序扫描更快。如果正则表达式不使用DFA,则速度会变慢,但我猜这取决于平台。关于在@后引用我的名字,我不太清楚,我也看到其他用户这样做了,因为我的显示名称中有一个空格。 - Akash Kava
1
我已经澄清了,在简单的分隔符中,string.split更快,但是对于可能涉及前瞻的复杂分隔符,正则表达式是唯一的选择。 - Akash Kava
默认情况下,对答案的评论是对作者的回复,因此明确提到作者是多余的(并且被 SO 系统省略)。 - iheanyi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接