【问题标题】:C# performance of StringBuilder ToString vs String SubstringStringBuilder ToString 与 String Substring 的 C# 性能
【发布时间】:2012-07-25 17:59:56
【问题描述】:

拥有一个字符串然后为此字符串调用子字符串更快,其中第一个子字符串将是初始字符串,而每个新的子字符串都是从初始子字符串到其结尾的一小部分?或者使用 StringBuilder 并从一开始就越来越多地切断,然后总是使用 ToString 从收缩的字符串中?

这个link 描述了StringBuilder ToString 方法仅在新线程访问StringBuilder 或返回的String 远小于当前分配的空间时才分配新空间。这听起来比使用 Substring 更快。我可以在implementation 中看到这个逻辑,直到 .Net Framework 3.5。在 4.0 版中,可以立即调用 FastAllocateString(或多或少类似于 String Substring)。是不是和之前的框架版本逻辑一样,只是现在隐藏了?

我为什么需要它:

编辑:更新说明: 我有一个字符串和一组用户给定的正则表达式和一个上下文。上下文告诉我当前哪些正则表达式会很有趣,可以尝试与字符串的开头匹配。成功匹配后,字符串的开始现在位于最后一次匹配结束的位置之后。现在可能有不同的背景。另外我想知道上次哪个正则表达式与开始匹配。 由于多次执行此操作,因此性能应该尽可能好。

为了避免搜索整个(剩余的)字符串,我会使用开始锚(^),这样可以尽快中止搜索(在知道开始不匹配之后)。如果这样做,我会遇到问题,即我不能将 Match 方法的起始索引参数与 0 以外的任何值一起使用。否则,由于锚点,将永远不会有匹配。

所以我觉得我现在有两种可能:

1) 始终对输入字符串使用 Substring 方法,并为当前位置保留和索引。

2) 使用 StringBuilder 并在匹配成功时始终删除输入的开头。然后调用 ToString 方法查看新的开始是否与下一个 Regex 匹配。

上述一种或两种方法的性能是否可以接受,还是有另一种更快的方法?

Edit2: 关于 StringBuilder 和 String:如 here 所述,StringBuilder 的实现现在立即分配空间,而以前这会延迟到 StringBuilder 字符串被更改(所有情况都是如此)我的要求的时间)。所以我猜 Substring 和 ToString 与 Kendall Frey 的纯正则表达式解决方案相比都非常慢。

【问题讨论】:

  • 您可能会考虑发布正则表达式,因为它可能能够被调整以自行满足您的需求。为好问题 +1。
  • Regex 可以自动执行此操作。 \G 匹配上一场比赛的结尾。示例:refiddle.com/2qf
  • @Kendall Frey 这看起来很有趣,我去看看!
  • 我发布了一个更完整的答案。
  • @Mike 它可以是任何正则表达式,并且在一次执行期间也不一定是相同的正则表达式。

标签: c# .net regex string performance


【解决方案1】:

您不需要这样做。 .NET 正则表达式引擎包含一项功能,可让您使用\G anchor 匹配上一个匹配项之后的字符串。

示例正则表达式:

\Gcat

示例字符串:

catcatcatdogcat

匹配:

(cat)(cat)(cat)dogcat

编辑:我认为正则表达式不会让您记住多个正则表达式之间的\G 锚点位置。相反,您可以使用Regex.Match(string, int) 重载在某个点开始您的字符串,并使用\G 锚来匹配起始位置。

【讨论】:

  • 当我只有一个重复使用的正则表达式但我有更多时,我认为这很有帮助。
  • 如果您只是动态地将 \G 添加到正则表达式的开头怎么办?他们来自哪里?用户?
  • 来自用户。我可以添加 \G。但据我了解,我不能继续使用上一场比赛的新正则表达式,还是我错了?我认为这只适用于 Perl
  • 哦,一个字符串需要多个正则表达式?那么拆分它们有什么意义呢?
  • 我不太明白您所说的“拆分它们”是什么意思。我有一个字符串和一组正则表达式和一个上下文。上下文告诉我当前哪些正则表达式会与字符串的开头相匹配。成功匹配后,字符串的开始现在位于最后一次匹配结束的位置之后。现在可能有不同的背景。另外我想知道哪个正则表达式匹配。我想我会在我最初的问题中更新这个解释,因为它可能会澄清一些事情。
【解决方案2】:

许多字符串操作方法都有带有开始/结束或开始/长度对的版本。

Regex.Match 可用于匹配子字符串,这可能比分割字符串或插入标记字符更快。

public Match Match(string input, int beginning, int length)

注意:与任何性能问题一样,您需要尝试变体并衡量自己的您的数据。

【讨论】:

  • 问题是我不知道长度。它可以是从一个字符到字符串其余部分的所有内容。
猜你喜欢
  • 1970-01-01
  • 2020-06-01
  • 2021-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多