我有以下代码:
string pattern = @"(?:\S+\s){1,6}\S*" + search + @"\S*(?:\s\S+){1,6}";
String dbContents = row[2].ToString();
var matches = Regex.Matches(dbContents, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
for (int i = 0; i < matches.Count; i++)
{
if (i == 3)
break;
Contents += String.Format("... {0} ...", matches[i].Value);
}
我想要完成的是在搜索词之前获得一到六个单词,在搜索词之后获得1-6个单词。执行代码时,性能在for循环“matches.Count”上命中。对于非常大的字符串,它需要花费一分钟来执行。我很困惑为什么以及如何解决这个问题。
答案 0 :(得分:10)
为了找到计数,必须找到 all 匹配才能对它们进行计数。鉴于你无论如何都要在三点之后停下来,这似乎有点无意义。
将MatchCollection
的延迟评估与LINQ中的Take
方法结合使用,只进行前三次匹配。通常,在循环中使用StringBuilder
而不是字符串连接也是个好主意:
StringBuilder builder = new StringBuilder(...);
foreach (var match in matches.Cast<Match>().Take(3))
{
builder.AppendFormat("... {0} ...", matches[i].Value);
}
(StringBuilder
更改可能不会在这里产生太大的影响,但这是一个很好的习惯。Cast
方法是必需的,因为Enumerable.Take
仅适用于通用IEnumerable<T>
类型。)
答案 1 :(得分:3)
来自MSDN:
Matches
方法使用延迟评估来填充返回的 MatchCollection对象。访问此集合的成员,例如 MatchCollection.Count和MatchCollection.CopyTo导致集合 立即填充。为了利用懒惰的评估,你 应该使用诸如foreach
之类的构造来迭代集合 C#
底线:将代码更改为使用foreach
。
答案 2 :(得分:3)
另一种方法是拨打Match
,然后拨打NextMatch
,如下所示:
var match = Regex.Match(dbContents, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
for (int i = 0; i < 3 && match.Success; i++)
{
Contents += String.Format("... {0} ...", matches[i].Value);
match = match.NextMatch();
}