【问题标题】:Find the last occurrence of a number in a string, and split the string by that value查找字符串中最后一次出现的数字,并按该值拆分字符串
【发布时间】:2021-12-02 03:03:31
【问题描述】:

我想要完成的是找到字符串中的最后一个数字并按该值分割。

string packageSize = "4/8.75LB";

上面我有一个字符串,我想将其拆分为一个字符串数组,并将它们放入数据库中的两个不同列中。第一部分是小数,最后一部分是字符串或 varchar。

我在下面有这段代码,它似乎正在工作。只是想知道是否有更好的解决方案,或者我错过了一个已回答的问题。

string value = Regex.Match(packageSize, @"(\d+)(?!.*\d)", RegexOptions.RightToLeft).ToString();
int lastIndex = packageSize.LastIndexOf(value) + value.Length;
string packageLoad = packageSize.Substring(0, lastIndex);
decimal loadDecimal = Convert.ToDecimal(packageLoad);

感谢您的帮助!

【问题讨论】:

    标签: c# regex split


    【解决方案1】:

    你可以使用

    var output = Regex.Split(packageSize, @"(\d)(?=\D*$)");
    

    (\d)(?=\D*$) 正则表达式匹配并捕获带有 (\d) 的数字,该数字也与 Regex.Split 返回(它输出捕获的子字符串)。 (?=\D*$) 确保 (\d) 匹配字符串中的最后一个数字。

    C# demo

    var packageSize = "4/8.75LB";
    var result = Regex.Split(packageSize, @"(\d)(?=\D*$)");
    foreach (var s in result)
        Console.WriteLine(s);
    
    // => 4/8.7
    //    5
    //    LB
    

    如果您需要确保正则表达式拆分确实发生,请检查输出数组的长度是否不等于1

    var packageSize = "4/8.75LB";
    //var packageSize = "LB"; // => 'LB' did not match the regex.
    var result = Regex.Split(packageSize, @"(\d)(?=\D*$)");
    if (result.GetLength(0) != 1) { // We have found a match
        foreach (var s in result)
            Console.WriteLine(s);
    }
    else
    {
        Console.WriteLine($"'{packageSize}' did not match the regex.");
    }
    

    this C# demo

    另外,如果只需要匹配 ASCII 数字,请使用Regex.Split(packageSize, @"(\d)(?=\D*$)", RegexOptions.ECMAScript)

    【讨论】:

      【解决方案2】:

      您可以在匹配最后一个数字之前的第一部分和匹配最后一个数字之后的第二部分使用 2 个捕获组。

      如果您希望每个组至少匹配一个字符,请将量词更改为 + 而不是 *

      ^(.*)[0-9](\D*)$
      
      • ^ 字符串开始
      • (.*)捕获组1,匹配任意字符
      • [0-9] 匹配单个数字 0-9
      • (\D*)捕获组2,可选匹配非数字
      • $ 字符串结束

      Regex demo

      例如

      string packageSize = "4/8.75LB";
      Regex r = new Regex(@"^(.*?)[0-9](\D*)$");
      foreach (Match m in r.Matches(packageSize))
      {
          Console.WriteLine(m.Groups[1].Value);
          Console.WriteLine(m.Groups[2].Value);
      }
      

      输出

      4/8.7
      LB
      

      【讨论】:

      • (.*)\d(\D*) 可以吗?
      • @CaiusJard 你说的没错,内容多在最后,回溯会少。
      【解决方案3】:

      “我想找到最后一位,并将字符串分成两边的两个”

      在性能方面,我认为你不会比循环做得更好:

      for(int i = str.Length-1; i>=0; i--)
        if(Char.IsDigit(str[i])){
          return (str[..i], str[(i+1)..]);
        }
      

      它返回一个("4/8.7", "LB")的元组

      --

      您可以将其调整为以下之一:

      var i = str.LastIndexOfAny("0123456789".ToCharArray());
      
      var i = Array.FindLastIndex(str.ToCharArray(), Char.IsDigit);
      
      return (str[..i], str[(i+1)..]);
      

      让我感到困惑的是,您在 cmets 中给出的规范与您在问题中给出的代码完全不同。您的代码“有效”,但4/8.7 不可能Convert.ToDecimal..

      【讨论】:

        【解决方案4】:

        不是 100% 确定我是否正确理解了要求,但是此正则表达式将捕获第一组中输入字符串中的最后一个数字(无论是否为十进制)和第二组中的以下字符:

        (\d+(?:\.\d+)?)(\D*)$
        

        因此,输入字符串"4/8.75LB" 将被拆分为:

        • 第 1 组:"8.75"
        • 第 2 组:"LB"

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-31
          • 2012-03-23
          • 2014-01-12
          • 2017-04-29
          • 2014-01-21
          • 2013-12-28
          相关资源
          最近更新 更多