【问题标题】:Matching an integer between the brackets匹配括号之间的整数
【发布时间】:2012-09-11 13:25:41
【问题描述】:

我收到一堆格式如下的字符串:

ASDF [         6]

ZXC[1]

OtPasd[ 4 ]

asdffa[   7]

我需要检索有效字符串括号之间的整数。只要满足以下条件,字符串就有效:

  1. 括号之间只有空格。 IE:“ZXCV[a2]”无效
  2. 所有括号都正确闭合。即:“qwr[2”无效
  3. 所有字符串都只有一个开/关括号。 IE:“zxcf[4]]]”无效

我最好避免使用正则表达式,因为我得到了大量的字符串,所以计算量不大的东西会更好。

验证和检索整数的最简洁且最快的方法是什么?

编辑:我决定使用正则表达式。

【问题讨论】:

  • 您应该向我们展示您的尝试。我可以理解这很难学习,但你至少应该尝试一些东西并展示出来。
  • 你为什么放弃正则表达式的想法?到目前为止,我认为这是获取您的数字的最简单方法,并且可能与任何其他解决方案一样快。过早的优化是万恶之源!
  • 使用String.IndexOfString.TrimInt.TryParse 的组合似乎很有可能。但是,我认为您应该重新考虑使用正则表达式,它们可能不像您最初认为的那样昂贵。
  • @trailmax 阿门!此外,正则表达式可能会比手动拆分、修剪等更强大。
  • 使用正则表达式,如果发现它是一个瓶颈,则提高性能。编写干净的工作可维护代码,然后编写快速代码。别忘了,在 C# 中,Regex 可以编译

标签: c# .net regex string


【解决方案1】:

在我个人看来,最干净的解决方案是使用正则表达式。但与其猜测它是否是计算密集型的,我宁愿对它进行基准测试。这是代码。

const int Count = 10000000;
const string testString = "<whatever>";

// Solution No. 1: use Regex.Match()    
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < Count; i++)
{
    var match = Regex.Match(@"\[\s*(\d+)\s*\]$", testString);
    if (!match.Success)
        continue;
    var number = int.Parse(match.Groups[1].Value);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

// Solution No. 2: use IndexOf() and Substring() shenanigans
sw.Start();
for (int i = 0; i < Count; i++)
{
    var lb = testString.IndexOf('[');
    var rb = testString.LastIndexOf(']');
    if (lb < 0 || rb != testString.Length - 1)
        continue;
    var str = testString.Substring(lb + 1, rb - lb - 1);
    int number;
    if (!int.TryParse(str, out number))
        continue;
    // use the number
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

结果如下:

Solution  |  testString  |   Time (ms)  | Comment
----------|--------------|--------------|-----------------------
     1    | abc [      ] |    4476      | Invalid input string
     2    | abc [      ] |    6594      | Invalid input string
     1    | abc[1234]    |    4446      | Valid input string
     2    | abc[1234]    |    6290      | Valid input string

如您所见,正则表达式解决方案不仅更短更简洁,而且实际上更快。如果您使用不同的输入字符串,您会注意到输入字符串越长,第一种解决方案和第二种解决方案之间的差距就越大。

【讨论】:

  • @Igor Korkhov,通过存储已编译的正则表达式可能会更快。 var regex = new Regex(@"\[\s*(\d+)\s*\]$", RegexOptions.Compiled );
  • @CaffGeek: 不是真的,因为 static Regex.Match() 会自动缓存最后 10 个左右编译的正则表达式。
  • @IgorKorkhov,我注意到了不同之处,但可能是创建新的正则表达式对象的成本,而不是正则表达式编译节省了时间。
【解决方案2】:

试试这个正则表达式:

\[\s*(\d+)\s*\]$

【讨论】:

  • 也匹配括号。我只想要括号内的整数。即: asdf [ 3 ] 给你 [ 3 ] 回来
【解决方案3】:

使用这个正则表达式(?m)(?!&lt;=\[)(\[\s*)(\d+)(\s*\])(?!\]) 你在匹配组中的整数

【讨论】:

  • 也匹配括号。我只想要括号内的整数。即: asdf [ 3 ] 给你 [ 3 ] 回来
  • 不是。 MatchCollection a = Regex.Matches(s, @"(?m)(?!
【解决方案4】:

如果您想避免使用 Regex... 使用 IndexOf/LastIndexOf 然后解析剩余的字符串是否适合您的需要?

【讨论】:

    【解决方案5】:

    要获得括号之间的 int,您也可以尝试这种方式:

    string tmpString = "ASDF [         6]";
    int start = tmpString.IndexOf('[') + 1;
    int length = tmpString.IndexOf(']') - start;
    string subString = tmpString.Substring(start, length);
    int tempInt;
    if(Int.TryParse(subString, out tempInt))
    return tempInt;
    

    【讨论】:

    • 好主意,但需要对“aasdf[[[5]]][]”等案例进行更多工作/验证。但是让我们为 l46kok 留下一些工作 -)
    • 确实,我们不需要把我认为的所有代码都给他 :) 但是当他在这里结合一些问题时,他的答案就会走得更远
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多