优化我的正则表达式匹配的最佳方法是什么

本文关键字:最佳 方法 是什么 我的 正则表达式 优化 | 更新日期: 2023-09-27 18:35:37

我有一个带有文本框的应用程序。用户在此框中输入文本。

我在该文本框中的 OnKeyUp 事件中触发了以下函数

private void bxItemText_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{               
    // rules is an array of regex strings
    foreach (string rule in rules)
    {
        Regex regex = new Regex(rule);
        if (regex.Match(text.Trim().ToLower()))
        {
            // matched rule is a variable
            matchedRule = rule;
            break;
        }
    }
}

我有大约 12 个字符串rules,尽管这可能会有所不同。

一旦文本框中的文本长度大于 80 个字符,性能就会开始下降。 在 100 个字符后键入字母需要一秒钟才能显示。

如何优化?我应该在每次第三次 KeyUp 上匹配吗?我应该完全放弃 KeyUp 并每隔几秒钟自动匹配一次吗?

优化我的正则表达式匹配的最佳方法是什么

如何优化?我应该在每次第三次 KeyUp 上匹配吗?我应该完全放弃 KeyUp 并每隔几秒钟自动匹配一次吗?

我会选择第二个选项,即放弃KeyUp并每隔几秒钟触发一次验证,或者更好的是,当TextBox失去焦点时触发验证。

另一方面,我应该建议事先缓存正则表达式并编译它们,因为看起来您似乎在一遍又一遍地使用它们,换句话说,您应该将它们存储为已编译的正则表达式对象时,而不是将规则存储为该数组中的字符串添加或加载它们。

使用static方法调用而不是每次都创建新对象, static调用使用caching功能:优化正则表达式性能,第一部分:使用正则表达式类和正则表达式对象。

这将是性能的重大改进,然后您可以提供正则表达式(规则)以查看是否可以在正则表达式中进行一些优化。

其他资源 :

  • 优化正则表达式性能,第二部分:负责回溯
  • 优化正则表达式性能,第 3 部分

在正则表达式级别将字符串组合为一个字符串将比代码中的 foreach 更快。将两个正则表达式合并为一个

如果您需要确定每个新符号的模式,并且您关心性能,那么最终状态机似乎是最佳选择......这是更难的方式。应为每个符号指定允许的下一个符号列表。如果可能的话,OnKeyUp你只需走下一个州。您将拥有输入文本当前匹配的模式数量。我可以找到一些有用的参考资料:

密克罗尼西亚联邦示例

家伙解释如何将正则表达式转换为 FSM

正则表达式 - FSM 转换讨论

您不需要每次都创建新的正则表达式对象。如果之前使用过,使用静态调用也将缓存模式(自 .Net 2 以来)。这是我如何重写它

matchedRule = Rules.FirstOrDefault( rule => Regex.IsMatch(text.Trim().ToLower(), rule)) ;

鉴于您似乎正在匹配关键字,您能否对已编辑的文本的当前部分(即在光标附近)执行匹配?设计起来可能很棘手,尤其是对于粘贴或撤消等操作,但可以大幅提高性能。

预编译正则表达式(使用 RegexOptions.Compiled )。另外,您能否通过扩展正则表达式来使TrimToLower变得多余?您为每个规则运行TrimToLower一次,即使您无法完全消除它们,效率也很低

您可以尝试使您的规则相互排斥 - 这应该会加快速度。我做了一个简短的测试:与以下内容匹配

"猫|汽车|驾驶室|盒子|气球|按钮"

可以这样写来加快

速度
"ca(t|r|b)

|b(ox|alloon|utton)"