-7

我必须用 C# 编写 RegEx 才能获得

最大上限 = 70;

  • 用户可以用 , 分隔输入多个值

    例如10,20,30,35-40,45,50-55 //Valid

  • 用户可以输入多个值 - 分隔

    例如10,20-30,35-40 //Valid

  • 用户可以添加最大限制变量值

    例如10,20-30,35-40,71-MaxUpperLimit //Invalid ,例如10,20-30,35-40,50-MaxUpperLimit //Valid

  • 用户不能输入任何超过 MaxUppLimit 的值

    例如45-71 //Invalid

4

4 回答 4

4

我认为这是一个挑战,但你下次真的应该尝试一下。

所以这是一个带有m修饰符的完整正则表达式解决方案:

^
  (?:
     (?:[0-6]?\d|70)(?:-[0-6]?\d|70)?
  )
  (?:
     ,(?:[0-6]?\d|70)(?:-[0-6]?\d|70)?
  )*
$

解释:

  • ^: 行首。
  • (?:: 分组但不捕获。
    • (?:: 分组但不捕获。
    • [0-6]?\d|70: 匹配 00 直到数字 70
    • (?:-[0-6]?\d|70)?: 匹配-后跟一个从 00 到 70 的数字,这是可选的
  • ): 结束组
  • (?:,(?:[0-6]?\d|70)(?:-[0-6]?\d|70)?)*:匹配,后跟我上面解释的内容,全部 0 次或更多次
  • $: 行结束
  • m modifier:分别制作^$匹配行的开始和结束

在线演示

注意:这不会考虑逻辑顺序,例如70-50匹配。

于 2013-05-27T13:50:48.080 回答
4

虽然正则表达式可能只适用于数字,但MaxUpperLimit它使事情变得足够复杂,以至于它可能更适合解析器。

这个想法是简单地将字符串拆分为使用,分隔符的组件,这将为您提供类似于字符串数组的内容(调用此步骤 1):

10
20
30
35-40
45
50-55

然后,对于其中的每一个,如果字符串还没有-字符,第 2 步首先修改字符串(到适当的范围而不是单个值),以便您最终得到:

10-10
20-20
30-30
35-40
45-45
50-55

然后,对于其中的每一个,使用-. 这将为您提供 2 个或 3 个或更多元素数组,后者无效(因为它们是格式错误的数组,例如1-7-11)。

然后,对于第 4 步,您检查这些数组值(由于之前执行的检查,此时总是有两个)以检查是否有字符串MaxUpperLimit。如果是,只需将它们转换为正确的值,在您的情况下为 string "70"

对于第 5 步,您只需验证它们是否为数字,并检查范围是否有效。这涉及确保第二个值大于或等于第一个值,并且可能第一个值大于或等于上一个范围的第二个如果您想确保不允许类似:

10-15,13-25

所以,一次拿一个例子,第一个:

10,20,30,35-40,45,50-55 // Valid
Step 1: (10)        (20)        (30)        (35-40)     (45)        (50-55)
Step 2: (10-10)     (20-20)     (30-30)     (35-40)     (45-45)     (50-55)
Step 3: ((10) (10)) ((20) (20)) ((30) (30)) ((35) (40)) ((45) (45)) ((50) (55))
Step 4: no change
Step 5: all valid

第二个包含与第一个完全相同的过程。

第三个也很好,直到第 5 步。第 4 步转换((71) (MaxUpperLimit))((71) (70)),然后第 5 步验证失败,因为第二个值小于第一个值。

((50) (MaxUpperLimit))在您的第四个示例中不是这种情况,因为((50) (70)它是一个有效范围。

同样,45-71您的第五个示例中的 也不会验证,因为该数字71超出了允许的值。


在伪代码中,您要查找的内容类似于以下内容。首先是一些代码,它检查单个完全指定的范围是否有效。

def isValidRange (strarray, prevupper):
    lower = int(strarray[0])
    upper = int(strarray[1])
    if lower < 1 or upper > MaxUpperLimit:
        return false
    if lower > upper or lower < prevupper:
        return false
    return true

接下来,如上详述的步骤:

def isValidRangeList(str):
    # Step 1

    strarray1 = str.split(",")

    prevupper = -1
    for each item in strarray1:
        # Step 2

        if not item.contains("-"):
            item = item + "-" + item

        # Step 3

        strarray2 = item.split("-")
        if strarray2.length() > 2:
            return false

        # Step 4

        if strarray2[0] == "MaxUpperLimit":
            strarray2[0] = MaxUpperLimit
        if strarray2[1] == "MaxUpperLimit":
            strarray2[1] = MaxUpperLimit

        # Step 5

        if not isValidRange( strarray2, prevupper):
            return false
        prevupper = int(strarray2[0])

    return true

当然,该伪代码只是验证输入数据(除了我自己的头脑之外,它未经测试,因此您可能需要一些调试)。毫无疑问,您会发现将范围添加到结构集合以便以后使用它们很有用。

于 2013-05-27T13:30:07.097 回答
0

检查限制是否太高:int MaxUpperLimit = 70; 字符串输入 = "10,20-30,35-40,710-MaxUpperLimit";

        input = input.Replace("MaxUpperLimit", MaxUpperLimit.ToString());

        bool isLimitExceeded = false;
        int result = 0;

        foreach (var komma in input.Split(",".ToCharArray()))
        {
            if (komma.Contains("-"))
            {
                foreach (var minus in komma.Split("-".ToCharArray()))
                {
                    if (!Int32.TryParse(minus, out result) || result > MaxUpperLimit)
                    {
                        isLimitExceeded = true;
                        break;
                    }
                }
            }
            else
            {
                if (!Int32.TryParse(komma, out result) || result > MaxUpperLimit || isLimitExceeded)
                {
                    isLimitExceeded = true;
                    break;
                }
            }
        }
于 2013-05-27T13:46:32.550 回答
0

尝试这个:

bool valid = str.Replace("MaxUpperLimit", MaxUpperLimit).Split(',').Select(p => p
                                     .Split('-')
                                     .Select(s=>s.Trim()).ToArray())
            .All(subPart => {
                    int i1, i2;
                    return (subPart.Length == 1 && int.TryParse(subPart[0], out i1) && i1 <= MaxUpperLimit) 
                    || (subPart.Length == 2 
                            && int.TryParse(subPart[0], out i1) && i1 < MaxUpperLimit 
                            && int.TryParse(subPart[1], out i2) && i2 <= MaxUpperLimit 
                            && i1 < i2);
                });
于 2013-05-27T13:56:58.897 回答