简体   繁体   中英

Regex for consecutive numbers

I want to check if a number is consecutive for example:

12345 is consecutive but 54321 is also consecutive.

Now my regex I use only says 12345 is consecutive.

String consecutive = "^(?:0?123(45?)?|1?23456?|2?34567?|3?45678?|4?56789?|(5?6)?7890?|\n" +
                "         (0?1)?2345678?(90$)?|1?23456789?|2?345678(90?)?)$";

How can I change this regex to match the other one to? It must be for 5 digits.

Is there a better way then this regex?

I don't think regex is the right answer to this question. It's possible, though (shudder!):

Pattern regex = Pattern.compile(
    "\\b                                                       \n" +
    "(?:                                                       \n" +
    " (?:                                                      \n" +
    "  0(?=1|\\b)|                                             \n" +
    "  1(?=2|\\b)|                                             \n" +
    "  2(?=3|\\b)|                                             \n" +
    "  3(?=4|\\b)|                                             \n" +
    "  4(?=5|\\b)|                                             \n" +
    "  5(?=6|\\b)|                                             \n" +
    "  6(?=7|\\b)|                                             \n" +
    "  7(?=8|\\b)|                                             \n" +
    "  8(?=9|\\b)|                                             \n" +
    "  9\\b         # or 9(?=0|\\b) if you want to allow 890123\n" +
    " )+                                                       \n" +
    " |                                                        \n" +
    " (?:                                                      \n" +
    "  9(?=8|\\b)|                                             \n" +
    "  8(?=7|\\b)|                                             \n" +
    "  7(?=6|\\b)|                                             \n" +
    "  6(?=5|\\b)|                                             \n" +
    "  5(?=4|\\b)|                                             \n" +
    "  4(?=3|\\b)|                                             \n" +
    "  3(?=2|\\b)|                                             \n" +
    "  2(?=1|\\b)|                                             \n" +
    "  1(?=0|\\b)|                                             \n" +
    "  0\\b         # or 0(?=9|\\b) if you want to allow 321098\n" +
    " )+                                                       \n" +
    ")                                                         \n" +
    "\\b", 
    Pattern.COMMENTS);
Matcher regexMatcher = regex.matcher(subjectString);

See it live on regex101.com .

As many other commentators of this question I believe that this should not be done with regex. Regex is cool if you want to match repeating patterns of digits (like 111 ), but not for arbitrary sequences of digits (like 123 or 246 ). Since I was interested in the topic I wrote this code. The input string may be any sequence of characters (digits mixed with non-digits) and all consecutive digits of the given length will be returned.

public class ConNumberParser {

    public static List<String> findConsecutiveNumbers(String s, int length) {
        LinkedList<String> matches = new LinkedList<>();

        // seek to first digit
        int i = 0;
        while (i < s.length() && !Character.isDigit(s.charAt(i))) {
            i++;
        }
        // store the beginning of a consecutive series
        Integer matchedIndex = i;
        // and the direction
        Boolean increasing = null;

        for (i++; i < s.length(); i++) {
            final char c = s.charAt(i);
            if (Character.isDigit(c)) {
                if (null == matchedIndex) {
                    // first digit after other characters
                    matchedIndex = i;
                    increasing = null;
                    continue;
                }
                int difference = Character.getNumericValue(c) - Character.getNumericValue(s.charAt(i - 1));
                if (Math.abs(difference) > 1) {
                    // no conescutive digits
                    matchedIndex = i;
                    increasing = null;
                    continue;
                }
                if (length > 2) {
                    if (null == increasing) {
                        // found first consecutive digit
                        increasing = (difference == 1);
                        continue;
                    }
                    final int expectedDiff = increasing ? 1 : -1;
                    if (difference != expectedDiff) {
                        // no conescutive digits in the right direction
                        matchedIndex = i - 1;
                        increasing = (difference == 1);
                        continue;
                    }
                }
                if (i - matchedIndex + 1 == length) {
                    // consecutive digits of given length found
                    matches.add(s.substring(matchedIndex, matchedIndex + length));
                    matchedIndex++; // move by one to keep matching overlapping
                                    // sequences
                }
            } else {
                matchedIndex = null;
            }
        }

        return matches;
    }

    public static void main(String[] args) {
        String test = "A12345b321";
        List<String> m = findConsecutiveNumbers(test, 3);
        System.out.print(test + " length=3: ");
        System.out.println(m.toString());

        String test2 = "Ax.*1290134543b3210";
        List<String> m2 = findConsecutiveNumbers(test2, 3);
        System.out.print(test2 + " length=3: ");
        System.out.println(m2.toString());

        List<String> m3 = findConsecutiveNumbers(test2, 2);
        System.out.print(test2 + " length=2: ");
        System.out.println(m3.toString());
    }

}

Which yields the expected result:

A12345b321 length=3: [123, 234, 345, 321]
Ax.*1290134543b3210 length=3: [345, 543, 321, 210]
Ax.*1290134543b3210 length=2: [12, 01, 34, 45, 54, 43, 32, 21, 10]

Found regex to hard so I did it this way:

  public static boolean isConsecutive(final String pinCode)
{
    int [] digits = new int [pinCode.length()];
    int [] differences = new int [pinCode.length()-1];
    int temp = 0;

    for(int i = 0; i < pinCode.length(); i++)
        digits[i] = Integer.parseInt(String.valueOf(pinCode.charAt(i)));

    for(int i = 0; i < digits.length -1; i++)
        differences[i] = Math.abs(digits[i] - digits[i+1]);

    if(differences.length != 0) {
        temp = differences[0];
        for (int i = 1; i < differences.length; i++)
            if (temp != differences[i])
                return false;
    }

    return true;
}

How about this one?

function test(r) {
    s = r.toString();
    if(s.length == 2) {
        return Math.abs(parseInt(s.split('')[0]) - parseInt(s.split('')[s.length-1])) == 1;
    } else {
        t = parseInt(s.split('')[0]) + parseInt(s.split('')[s.length-1]); 
        s = '' + (parseInt(s) + parseInt(s.split('').reverse().join(''))) / t;
        return new RegExp('1{' + s.split('').length + '}').test(s);
    }
}

Does it need to be Regex? Off the top of my head you could split any incomming string into the characters, convert to a number and then check if b = a + 1 || b = a - 1 (setting some flag at the start to figure out if you are incrementing or decrementing.


EDIT:

The post here might help you out.

This is the regex it suggests:

/(^|(.)(?!\\2))(\\d)\\3{3}(?!\\3)/ (NB This is only for 4 characters)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM