1

我需要从一个字符串version(最多 3 个字符,如 sql varchar(3))中获取具有以下简单规则的“下一个版本”:

如果它的最后一个字符构成一个数字,则增加它,如果它总是最多适合 3 个字符,否则,保持原样。

说 "Hi1" => "Hi2", "H9" => "H10" 但 "xx9" 将保持不变。

  Public Shared Function GetNextVersion(oldVersion As String) As String
    Dim newVersion As String = String.Empty
    If Regex.IsMatch(oldVersion, "?????") Then
      Return newVersion
    Else
      Return oldVersion
    End If
  End Function
4

2 回答 2

3

这将是您的正则表达式,它将匹配带有一组字母后跟一组数字的任何内容。

Public Dim regex As Regex = New Regex( _
      "^(?<prefix>.*?0*)(?<version>\d+)$", _
      RegexOptions.IgnoreCase _
        Or RegexOptions.CultureInvariant _
        Or RegexOptions.Compiled _
    )

它将包含两个命名的捕获组,“前缀”是初始字符,“版本”是您的版本。

将版本转换为 int,递增,并通过连接前缀和新版本返回新版本号。

所以,你最终会得到这样的东西

Public versionRegex As Regex = New Regex( _
   "^(?<prefix>.*?0*)(?<version>\d+)$", _
   RegexOptions.IgnoreCase _
     Or RegexOptions.CultureInvariant _
     Or RegexOptions.Compiled _
 )

Public Shared Function GetNextVersion(oldVersion As String) As String
    Dim matches = versionRegex.Matches(oldVersion)
    If (matches.Count <= 0) Then
        Return oldVersion
    End If

    Dim match = matches(0)
    Dim prefix = match.Groups.Item("prefix").Value
    Dim version = CInt(match.Groups.Item("version").Value)

    Return String.Format("{0}{1}", prefix, version + 1)
End Function
于 2012-09-28T15:23:32.353 回答
0

我不会使用正则表达式 正则
表达式是一个解析器,这比解析更具逻辑性
对于 3 个字符,正则表达式并不比蛮力快

战略就是绩效。
必须测试边缘情况并且有很多。
先做便宜货。
显然这是 C#

认为得到了所有的测试用例。

static void Main(string[] args)
    {
        System.Diagnostics.Debug.WriteLine(NewVer("H"));
        System.Diagnostics.Debug.WriteLine(NewVer("Hi"));
        System.Diagnostics.Debug.WriteLine(NewVer("Hii"));
        System.Diagnostics.Debug.WriteLine(NewVer("Hiii"));
        System.Diagnostics.Debug.WriteLine(NewVer("H1"));
        System.Diagnostics.Debug.WriteLine(NewVer("H9"));
        System.Diagnostics.Debug.WriteLine(NewVer("Hi1"));
        System.Diagnostics.Debug.WriteLine(NewVer("H19"));
        System.Diagnostics.Debug.WriteLine(NewVer("9"));
        System.Diagnostics.Debug.WriteLine(NewVer("09"));
        System.Diagnostics.Debug.WriteLine(NewVer("009"));
        System.Diagnostics.Debug.WriteLine(NewVer("7"));
        System.Diagnostics.Debug.WriteLine(NewVer("07"));
        System.Diagnostics.Debug.WriteLine(NewVer("27"));
        System.Diagnostics.Debug.WriteLine(NewVer("347"));
        System.Diagnostics.Debug.WriteLine(NewVer("19"));
        System.Diagnostics.Debug.WriteLine(NewVer("999"));
        System.Diagnostics.Debug.WriteLine(NewVer("998"));
        System.Diagnostics.Debug.WriteLine(NewVer("C99"));
        System.Diagnostics.Debug.WriteLine(NewVer("C08"));
        System.Diagnostics.Debug.WriteLine(NewVer("C09"));
        System.Diagnostics.Debug.WriteLine(NewVer("C11"));
    }

    public static string NewVer(string oldVer)
    {
        string newVer = oldVer.Trim();
        if (string.IsNullOrEmpty(newVer)) return oldVer;
        if (newVer.Length > 3) return oldVer;
        // at this point all code paths need char by postion
        // regex is not the appropriate tool
        Char[] chars = newVer.ToCharArray();
        if (!char.IsDigit(chars[chars.Length - 1])) return oldVer;
        byte lastDigit = byte.Parse(chars[chars.Length - 1].ToString());
        if (lastDigit != 9)
        {
            lastDigit++;
            StringBuilder sb = new StringBuilder();
            for (byte i = 0; i < chars.Length - 1; i++)
            {
                sb.Append(chars[i]);
            }
            sb.Append(lastDigit.ToString());
            return sb.ToString();
        }
        // at this point the last char is 9  and lot of edge cases 
        if (chars.Length == 1) return (lastDigit + 1).ToString();
        if (char.IsDigit(chars[chars.Length - 2]))
        {
            if (chars.Length == 2) return ((byte.Parse(newVer)) + 1).ToString();
            byte nextToLastDigit = byte.Parse(chars[chars.Length - 2].ToString());
            if (nextToLastDigit == 9)
            {
                if (char.IsDigit(chars[0]))
                {
                    byte firstOfthree = byte.Parse(chars[0].ToString());
                    if (firstOfthree == 9) return oldVer; // edge case 999
                    // all three digtis and not 999
                    return ((byte.Parse(newVer)) + 1).ToString();
                }
                // have c99
                return oldVer;
            }
            else
            {
                //have c 1-8 9 
                return chars[0].ToString() + (10 * nextToLastDigit + lastDigit + 1).ToString();        
            }
        }
        // at this point have c9 or cc9
        if (chars.Length == 3) return oldVer;
        // at this point have c9
        return chars[0].ToString() + "10";
    }
于 2012-09-28T15:05:29.943 回答