我正在编写一个C#应用程序,它在很多(约2500万)字符串上运行许多正则表达式(~10)。我确实试图谷歌这个,但任何搜索正则表达式“慢下来”充满了关于如何反向引用等减慢正则表达式的教程。我假设这不是我的问题,因为我的正则表达式开始快速而缓慢。
对于前一百万个字符串,每1000个字符串需要大约60ms才能运行正则表达式。到最后,它的速度减慢到大约需要600毫秒。有谁知道为什么?
情况更糟,但我通过使用RegEx
的实例而不是缓存版本并编译我可以使用的表达式来改进它。
我的一些正则表达式需要改变,例如:取决于用户的名字
mike said (\w*)
或john said (\w*)
我的理解是,无法编译这些正则表达式并传入参数(例如saidRegex.Match(inputString, userName)
)。
有人有任何建议吗?
[编辑准确反映速度 - 每1000字符串,而不是每串]
答案 0 :(得分:2)
这可能不是您关于RegEx性能下降的问题的直接答案 - 这有点令人着迷。但是 - 在阅读了上述所有评论和讨论后 - 我建议如下:
解析数据一次,将匹配的数据拆分为数据库表。看起来您正在尝试捕获以下字段:
Player_Name | Monetary_Value
如果您要创建一个包含每行这些值的数据库表,然后在创建它时捕获每个新行 - 解析它 - 并附加到数据表 - 您可以轻松地进行任何类型的分析/计算反对数据 - 无需一次又一次地解析25M行(这是一种浪费)。
此外 - 在第一次运行时,如果您要将25M记录分解为100,000个记录块,则运行算法250次(100,000 x 250 = 25,000,000) - 您可以享受所描述的所有性能放慢速度,因为你正在努力工作。
换句话说 - 请考虑以下事项:
按如下方式创建数据库表:
CREATE TABLE PlayerActions (
RowID INT PRIMARY KEY IDENTITY,
Player_Name VARCHAR(50) NOT NULL,
Monetary_Value MONEY NOT NULL
)
创建一个将25米行分解为100k块的算法。使用LINQ / EF5作为假设的示例。
public void ParseFullDataSet(IEnumerable<String> dataSource) {
var rowCount = dataSource.Count();
var setCount = Math.Floor(rowCount / 100000) + 1;
if (rowCount % 100000 != 0)
setCount++;
for (int i = 0; i < setCount; i++) {
var set = dataSource.Skip(i * 100000).Take(100000);
ParseSet(set);
}
}
public void ParseSet(IEnumerable<String> dataSource) {
String playerName = String.Empty;
decimal monetaryValue = 0.0m;
// Assume here that the method reflects your RegEx generator.
String regex = RegexFactory.Generate();
for (String data in dataSource) {
Match match = Regex.Match(data, regex);
if (match.Success) {
playerName = match.Groups[1].Value;
// Might want to add error handling here.
monetaryValue = Convert.ToDecimal(match.Groups[2].Value);
db.PlayerActions.Add(new PlayerAction() {
// ID = ..., // Set at DB layer using Auto_Increment
Player_Name = playerName,
Monetary_Value = monetaryValue
});
db.SaveChanges();
// If not using Entity Framework, use another method to insert
// a row to your database table.
}
}
}
运行上述一次以加载所有预先存在的数据。
在某个地方创建一个钩子,允许您检测新行的添加。每次创建新行时,请调用:
ParseSet(new List<String>() { newValue });
或如果一次创建倍数,请致电:
ParseSet(newValues); // Where newValues is an IEnumerable<String>
现在,您可以从数据中进行任何计算分析或数据挖掘,而无需担心动态超过25米的性能。
答案 1 :(得分:0)
Regex确实需要时间来计算。但是,U可以使用一些技巧使其紧凑。 您还可以在C#中使用字符串函数来避免正则表达式函数。
代码很长但可能会提高性能。 String有几个函数可以剪切和提取字符,并根据需要进行模式匹配。 例如:IndeOfAny,LastIndexOf,Contains ....
string str= "mon";
string[] str2= new string[] {"mon","tue","wed"};
if(str2.IndexOfAny(str) >= 0)
{
//success code//
}