我的英语能力很差,因为我不会说英语。 希望您能理解。
我已经在.Net中使用了Regex函数。 有一天,我尝试了使用117000字符串和46种模式调用Regex的Matches函数的测试。 结果,比2ms更快地生成了51870个令牌。
这里令人惊讶的事情是只花了2ms。 将生成的集合转换为List需要250毫秒。 (代码如下)。
var list = collection.Cast<Match>().Select(match => match.Value).ToList();
我简直不敢相信,所以尝试了几次,结果还是一样。
我很好奇为什么匹配Regex功能这么快。 是否在内部使用异步或并行机制?
在测试中,我像下面这样调用该函数。
var collection = Regex.Matches(targetString(117000), this.rule(46), RegexOptions.Multiline | RegexOptions.ExplicitCapture);
感谢您阅读。
完整的源代码如下。 请在test.txt中输入许多字符串。 为了简单起见,我删除了“ \ r”,“ \ n”,“ \ t”模式。 结果,生成的令牌的数量为45450。 谢谢您的关注。
class Program
{
static void Main(string[] args)
{
string targetString = File.ReadAllText("test.txt");
string pattern = "(\\breturn\\b)|(\\bwhile\\b)|(\\bconst\\b)|(\\belse\\b)|(\\bvoid\\b)|(\\bint\\b)|(\\bif\\b)|" +
"([_a-zA-Z][_a-zA-Z0-9]*)|([0-9]+)|" +
"(//.*$)|(\\!\\=)|(\\%\\=)|(\\>\\=)|(\\/\\=)|(\\+\\=)|(\\|\\|)|(\\-\\-)|(\\+\\+)|(\\*\\=)|(\\-\\=)|(\\<\\=)|(\\=\\=)|(\\&\\&)|(\\*\\/)|(\\/\\*)|(\\*)|(\\!)|(\\+)|(\\%)|(\\))|(\\;)|(\\()|(\\/)|" +
"(\\{)| (\\})| (\\-)| (\\])| (\\[)|(\\,)|(\\>)|(\\ )|(\\=)|(\\<)";
Stopwatch sw = new Stopwatch();
sw.Start();
var collection = Regex.Matches(targetString, pattern, RegexOptions.Multiline | RegexOptions.ExplicitCapture);
sw.Stop();
Console.WriteLine("Elapsed={0}", sw.Elapsed);
sw = new Stopwatch();
sw.Start();
var list = collection.Cast<Match>().Select(match => match.Value).ToList();
sw.Stop();
Console.WriteLine("Elapsed={0}", sw.Elapsed);
}
}
我的结果显示如下。
答案 0 :(得分:3)
RegExpMatches
方法返回一个包含匹配项的MatchCollection
对象。但是,此对象默认情况下在 lazy 模式下运行,这意味着它不会遍历整个字符串并立即查找所有匹配项,但始终仅在查找下一个匹配项时才查找。< / p>
根据需要在逐个匹配项中填充MatchCollection对象 基础。它等效于正则表达式引擎调用 Regex.Match方法重复并将每个匹配项添加到集合中。 通过集合的集合访问集合时使用此技术 GetEnumerator方法,或使用foreach访问该方法 语句(在C#中)或For Each ... Next语句(在Visual Basic中)。
因此,在您的代码中,实际的搜索不是在对Matches()
的调用上进行的,而是仅在尝试将MatchCollection
转换为List
时进行的。
要测量模式搜索的总时间,您可以通过访问代码中的Count
属性来强制进行直接评估。
Stopwatch sw = new Stopwatch();
sw.Start();
var collection = Regex.Matches(targetString, pattern, RegexOptions.Multiline | RegexOptions.ExplicitCapture);
int count = collection.Count; // Force immediate full evaluation
sw.Stop();
Console.WriteLine("Found {0}, Elapsed={1}", count, sw.Elapsed);