使用正则表达式匹配增加/减少序列

时间:2014-11-14 15:03:40

标签: c# regex

我想匹配任何只包含增加或减少数字的字符串。这意味着这些字符串将匹配:

123, 234567, 0123456789, 87654, 321

这些不会:

7891011, 1234566789, 987865, 134

我一直在寻找答案,all I found是使用正则表达式无法完成的。但是,我想在正则表达式中执行此操作,否则会在代码中弄乱。

感谢您的回答。

4 个答案:

答案 0 :(得分:5)

从技术上讲,可以使用前瞻,但看起来不太好。

提升模式的逻辑:

  1. 从字符串的开头
  2. 开始
  3. 仅匹配当前数字,以防它后跟下一个数字或字符串结尾。移到下一个位置。
  4. 重复2,直到我们到达字符串结尾。
  5. 123的例子:

    1. 从字符串的开头
    2. 开始
    3. 当前符号为0?没错。跳过。
    4. 当前符号为1?是。是后跟2还是字符串结尾?是。好的,转到下一个符号。
    5. 当前符号是2?是。是后跟3还是字符串结尾?是。好的,转到下一个符号。
    6. 目前的符号是3?是。它后跟4或字符串结束吗?是。好的,转到下一个符号。
    7. 当前符号是4?当前符号是5?不,......字符串结束了吗?是。
    8. 134的例子:

      1. 从字符串的开头
      2. 开始
      3. 当前符号为0?没错。跳过。
      4. 当前符号为1?是。是后跟2还是字符串结尾?不。错误,不匹配。
      5. 正则表达式匹配升序模式:

        ^(?:0(?=1|$))?(?:1(?=2|$))?(?:2(?=3|$))?(?:3(?=4|$))?(?:4(?=5|$))?(?:5(?=6|$))?(?:6(?=7|$))?(?:7(?=8|$))?(?:8(?=9|$))?9?$
        

        Regular expression visualization

        Debuggex Demo

        正则表达式匹配降序模式:

        ^(?:9(?=8|$))?(?:8(?=7|$))?(?:7(?=6|$))?(?:6(?=5|$))?(?:5(?=4|$))?(?:4(?=3|$))?(?:3(?=2|$))?(?:2(?=1|$))?(?:1(?=0|$))?0?$
        

        Regular expression visualization

        Debuggex Demo

        结合在一起:

        ^((?:0(?=1|$))?(?:1(?=2|$))?(?:2(?=3|$))?(?:3(?=4|$))?(?:4(?=5|$))?(?:5(?=6|$))?(?:6(?=7|$))?(?:7(?=8|$))?(?:8(?=9|$))?9?|(?:9(?=8|$))?(?:8(?=7|$))?(?:7(?=6|$))?(?:6(?=5|$))?(?:5(?=4|$))?(?:4(?=3|$))?(?:3(?=2|$))?(?:2(?=1|$))?(?:1(?=0|$))?0?)$
        

        Regular expression visualization

        Debuggex Demo

        Regex101 Demo

答案 1 :(得分:1)

代码不会比正则表达式更糟糕。正则表达式在数学上很糟糕。

这样的事情会做到:

bool IsSequentiallyIncreasing(string input)
{
    char? lastDigit = null;

    foreach (char c in input)
    {
        if (!c.IsDigit || (lastDigit != null && c != lastDigit + 1))
        {
            return false;
        }

        lastDigit = c;
    }

    return true;
}

所以你走过字符串中的所有字符,一旦遇到非数字或不是最后一位数字+ 1的数字,你就会返回false。

为减少而做同样的事情,你只需拨打IsSequentiallyIncreasing(input) || IsSequentiallyDecreasing(input)即可。我将由您来添加错误处理并将两种方法合并为一种。

答案 2 :(得分:1)

我创建了一个函数IsSequential

static bool IsSequential(string input)
{
    var nums = input.Select(Convert.ToInt32);

    int last = nums.First();
    foreach (var num in nums.Skip(1))
    {
        if (num < last) return false;
        last = num;
    }

    return true;
}

然后只需检查每个号码IsSequential,或者IsSequential是否反转。

var inputs = @"123, 234567, 0123456789, 87654, 321, 7891011, 1234566789, 987865";
var valids = inputs
                .Split(',')
                .Select(n => n.Trim())
                .Where(n => IsIncreasing(n) || IsIncreasing(new string(n.Reverse().ToArray())))
                .ToList();

如果您需要将它们精确地增加1,请使用if(num != last+1)

答案 3 :(得分:1)

没有可以执行此操作的正则表达式模式,但您可以使用正则表达式来帮助收集这些项目

List<Match> oMatches = new List<Match>();
String sData = "123, 234567, 0123456789, 87654, 321 , 7891011, 1234566789, 987865";
Regex.Replace(sData, @"\d+", delegate(Match oMatch)//delegate is run for each match as closure
{
    char? oLast = null;
    foreach (char oChar in oMatch.Value)//for each char
    {
        if ((oLast != null && Math.Abs(oChar - oLast) > 1))//not in sequense
            return oMatch.Value;//early return
        oLast = oChar;
    }
    oMatches.Add(oMatch)//add to outside collection
    return oMatch.Value; //return match itself because we don't actually want to replace anything
});