c# - 是否可以从字符串列表中快速提取位于切片中标签内的特定值?

标签 c# regex list optimization

我正在使用一个两步正则表达式来提取字符串列表中特定标记第一次出现的值:

Regex regexComplete = new Regex(
    @"MyNumberMarker"
    + @"[\d]+"
    + @"[\s]+Endmarker"
);

Regex regexOnlyNumber = new Regex(
    @"MyNumberMarker"
    + @"[\d]+"
);

int indexmyNumber = eintraegeListe.FindIndex(
    5,
    10000,
    x => regexComplete.IsMatch(x)
);

if (indexmyNumber >= 0)
{
    int myNumber = 0;
    string myNumberString = regexOnlyNumber.Match(regexComplete.Match(eintraegeListe[indexmyNumber]).Value).Value;
    myNumberString = myNumberString.Replace("MyNumberMarker", "").Replace("\n", "").Replace("\r", "").Trim();

    if (Int32.TryParse(myNumberString, out myNumber))
    {
        return myNumber;
    }
}

如您所见,我真正想要的值位于“MyNumberMarker”和“Endmarker”之间。它位于我使用 findIndex 命令搜索的列表的特定部分。然后我使用正则表达式提取完整的值+标签并将其简化为“仅”开始标签和值,然后手动删除开始标签,所有这些都可以是空格(包括\n和\r)。

现在这按预期工作得很好,但如果我这样做几千次,最后它会很慢。因此我的问题。 有没有更好(更快)的方法来做到这一点?

请注意:eintraegeListe 可以包含 100 到 30000 个条目。

例如,如果我有以下小列表:

[0]This is a test
[1]22.09.2015 01:00:00
[2]Until 22.09.2015 03:00:00
[3]................................
[4]................................
[5]........ TESTDATA
[6]...............................
[7]................................
[8]MyNumberMarker519 Endmarker
[9]This is a small
[10]Slice of Test data with
[11]520 - 1 as data.

我希望返回 519

最佳答案

由于您返回的是单个项目,因此 FindIndex 之后的代码的性能无关紧要:它只执行一次,并且需要一个字符串,因此在任何现代硬件上它都应该在几微秒内完成.

占用大量 CPU 的代码在 x => regexComplete.IsMatch(x) 调用中。您可以看出此代码大部分时间都返回 false,因为循环在第一次返回 true 时结束。

这意味着您应该针对负面情况进行优化,即尽快返回 false。实现此目的的一种方法是在使用正则表达式之前查找 "MyNumberMarker"。如果没有标记,则立即返回false;否则,退回到使用正则表达式,并从找到标记的位置开始:

int indexmyNumber = eintraegeListe.FindIndex(
    5,
    10000,
    x => {
        // Scan the string for the marker in non-regex mode
        int pos = x.IndexOf("MyNumberMarker", StringComparison.Ordinal);
        // If the marker is not there, do not bother with regex, and return false
        return pos < 0
             ? false
             // Only if the marker is there, check the match with regex.
             : regexComplete.IsMatch(x, pos);
    }
);

关于c# - 是否可以从字符串列表中快速提取位于切片中标签内的特定值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32717104/

相关文章:

c# - 寻找有关差异问题的解释

regex - 在Hive中使用regexp_extract提取数据

c# - 如何 "query"列表<T>

Python:创建元组列表

python - 检查子字符串匹配并创建新列表

c# - 如何在 nopCommerce 中为供应商和客户设置密码

c# - 使用 xml.Load 打开 HTML 文档

c# - 如何在特定线程上异步调用方法?

javascript - 转换任意字符串以在 JavaScript 中使用的函数

php - 使用正则表达式和 PHP 将段落拆分为句子