Справка с проверкой числа водительских прав regex

Мой ответ касается скорости только в тех случаях, когда мы не проверяем тип и не проверяем нули после приведения. Я добавил два дополнительных теста в код Джона Скита:

using System;
using System.Diagnostics;

class Test
{
    const int Size = 30000000;

    static void Main()
    {
        object[] values = new object[Size];

        for (int i = 0; i < Size; i++)
        {
            values[i] = "x";
        }
        FindLengthWithIsAndCast(values);
        FindLengthWithIsAndAs(values);
        FindLengthWithAsAndNullCheck(values);

        FindLengthWithCast(values);
        FindLengthWithAs(values);

        Console.ReadLine();
    }

    static void FindLengthWithIsAndCast(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            if (o is string)
            {
                string a = (string)o;
                len += a.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("Is and Cast: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }

    static void FindLengthWithIsAndAs(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            if (o is string)
            {
                string a = o as string;
                len += a.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("Is and As: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }

    static void FindLengthWithAsAndNullCheck(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            string a = o as string;
            if (a != null)
            {
                len += a.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("As and null check: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }
    static void FindLengthWithCast(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            string a = (string)o;
            len += a.Length;
        }
        sw.Stop();
        Console.WriteLine("Cast: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }

    static void FindLengthWithAs(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            string a = o as string;
            len += a.Length;
        }
        sw.Stop();
        Console.WriteLine("As: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }
}

Результат:

Is and Cast: 30000000 : 88
Is and As: 30000000 : 93
As and null check: 30000000 : 56
Cast: 30000000 : 66
As: 30000000 : 46

Не пытайтесь сосредоточиться на скорости (как я), потому что все это очень-очень быстро .

5
задан Ian Boyd 20 June 2009 в 13:17
поделиться

2 ответа

Trying to solve this with just one regex is probably a little hard as you need to keep track of multiple things. I'd suggest you try validating each of the properties separately (unless it makes sense to do otherwise).

For example you can verify the first and second properties easily by checking for a character class including all alphanumeric characters and a quantifier which tells that it should be present at most 9 times:

^[0-9a-zA-Z]{4,9}$

The anchors ^ and $ ensure that this will, in fact, match the entire string and not just a part of it. As Marc Gravell pointed out the string "aaaaa" will match the expression "a{3}" because it can match partially as well.

Checking the fifth property can be done similarly, although this time we don't care about the rest:

^..[0-9]{2}

Here the ^ character is an anchor for the start of the string, the dot (.) is a placeholder for an arbitrary character and we're checking for the third and fourth character being numeric again with a character class and a repetition quantifier.

Properties three and four are probably easiest validated by iterating through the string and keeping counters as you go along.

EDIT: Marc Gravell has a very nice solution for those two cases with regular expressions as well. Didn't think of those.

If you absolutely need to do this in one regular expression this will be a bit work (and probably neither faster nor more readable). Basically I'd start with enumerating all possible options such a string could look like. I am using a here as placeholder for an alphabetic characters and 1 as a placeholder for a number.

We need at least four characters (3) and the third and fourth are always fixed as numbers. For four-character strings this leaves us with only one option:

1111

Five-character strings may introduce a letter, though, with different placements:

a1111
1a111
1111a

and, as before, the all-numeric variant:

11111

Going on like this you can probably create special rules for each case (basically I'd divide this into "no letter", "one letter" and "two letters" and enumerate the different patterns for that. You can then string together all patterns with the pipe (|) character which is used as an alternative in regular expressions.

2
ответ дан 14 December 2019 в 01:15
поделиться

Должно быть одно регулярное выражение? Я бы упростил задачу, разделив их:

static bool IsValid(string input)
{
    return Regex.IsMatch(input, @"^[A-Za-z0-9]{4,9}$") // length and alphanumeric
        && Regex.IsMatch(input, "^..[0-9]{2}") // 3rd+4th are numeric
        && Regex.IsMatch(input, "(.*[0-9]){4}") // at least 4 numeric
        && !Regex.IsMatch(input, "(.*[A-Za-z]){3}"); // no more than 2 alpha
}
5
ответ дан 14 December 2019 в 01:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: