C++ Regex vs.string:find()用于简单单词边界
假设我只需要找出从文件中读取的行是否包含有限的单词集中的单词 这样做的一种方法是使用类似以下的C++ Regex vs.string:find()用于简单单词边界,c++,regex,performance,search,C++,Regex,Performance,Search,假设我只需要找出从文件中读取的行是否包含有限的单词集中的单词 这样做的一种方法是使用类似以下的 .*\y(good|better|best)\y.* if ( (readLine.find("good") != string::npos) || (readLine.find("better") != string::npos) || (readLine.find("best") != string::npos) ) { // line contains
.*\y(good|better|best)\y.*
if ( (readLine.find("good") != string::npos) ||
(readLine.find("better") != string::npos) ||
(readLine.find("best") != string::npos) )
{
// line contains a word from a finite set of words.
}
\y(good|better|best)\y
实现这一点的另一种方法是使用如下的伪代码:
.*\y(good|better|best)\y.*
if ( (readLine.find("good") != string::npos) ||
(readLine.find("better") != string::npos) ||
(readLine.find("best") != string::npos) )
{
// line contains a word from a finite set of words.
}
\y(good|better|best)\y
哪种方式性能更好?(即速度和CPU利用率)显然不是第二个(使用“查找”),因为您正在运行三个比较(需要遍历字符串至少3次),而不是一个比较。如果正则表达式引擎的工作原理与它应该的一样(我想它是这样的),那么它可能至少会快三倍。在进行测量之前,您不会知道哪个更快,但关键问题是:
string::find
的实现我把赌注押在正则表达式上,但再次强调:您必须测量以确保。正则表达式的性能会更好,但要去掉那些“*”部分。它们使代码复杂化,不起任何作用。类似这样的regexp:
.*\y(good|better|best)\y.*
if ( (readLine.find("good") != string::npos) ||
(readLine.find("better") != string::npos) ||
(readLine.find("best") != string::npos) )
{
// line contains a word from a finite set of words.
}
\y(good|better|best)\y
将在单个过程中搜索字符串。它从这个regexp构建的算法将首先查找\y,然后是字符1(g | b),然后是字符2(g=>go或b=>be),字符3(go=>goo或be=>bes | bet),字符4(go=>good或bes=>best或bett=>bett),等等,而不需要构建自己的状态机,这是最快的速度。Regex对我来说一直都是-每个人都知道它,而且它使用起来又快又容易。@Chuck每个人都知道Regex?这是多么不真实啊。:)这似乎很容易测量和测试,如果不进行测量,你就无法真正说出这一点。如果这些行足够短,它们可能适合CPU缓存的一行,并且
find
可能非常快。larsmans-嗯,是的,理论上,查找速度可能同样快,甚至更快。由于问题是性能,“大差异”案例将是一个很长的字符串;“大差异”的情况可能是从内存中的一大块文本中取出许多小行。赛斯:不一定,但我的直觉是,即使在cpu缓存中已经有许多小行的情况下,在它们上运行编译的正则表达式也会比在多个findsWow上运行更快!到目前为止,我收到的所有答案都很好,但这一个是最好的IMHO,因为它也简单地解释了regex引擎的工作原理。我将不得不接受这个答案(对不起,我没有足够的理由放弃投票,否则我会放弃投票给所有回答我问题的人)。如果你使用像谷歌的RE2这样的编译正则表达式引擎,搜索速度可能会与使用和不使用*
时相同。