Как проверить, имеет ли строка хотя бы 1 буквенный символ? - PullRequest
1 голос
/ 26 июля 2011

Мое приложение ASP.NET требует, чтобы я генерировал огромное количество случайных строк, каждая из которых содержала как минимум 1 алфавитный и числовой символ и должна была быть буквенно-цифровой в целом. Для этого моя логика заключается в том, чтобы снова сгенерировать код, если случайная строка числовая:

        public static string GenerateCode(int length)
        {
            if (length < 2 || length > 32)
            {
                throw new RSGException("Length cannot be less than 2 or greater than 32.");
            }
            string newcode = Guid.NewGuid().ToString("n").Substring(0, length).ToUpper();
            return newcode;
        }

        public static string GenerateNonNumericCode(int length)
        {
            string newcode = string.Empty;
            try
            {
                newcode = GenerateCode(length);
            }
            catch (Exception)
            {
                throw;
            }
            while (IsNumeric(newcode))
            {
                return GenerateNonNumericCode(length);
            }
            return newcode;
        }

        public static bool IsNumeric(string str)
        {
            bool isNumeric = false;
            try
            {
                long number = Convert.ToInt64(str);
                isNumeric = true;
            }
            catch (Exception)
            {
                isNumeric = false;
            }
            return isNumeric;
        }

Во время отладки он работает правильно, но когда я прошу его создать 10000 случайных строк, он не может обработать его должным образом. Когда я экспортирую эти данные в Excel, я нахожу в среднем не менее 20 строк, которые являются числовыми. Это проблема с моим кодом или C #? - Мой.
Если кто-то ищет код,

public static string GenerateCode(int length)
    {
        if (length < 2)
        {
            throw new A1Exception("Length cannot be less than 2.");
        }
        var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        var random = new Random();
        var result = new string(

        Enumerable.Repeat(chars, length)
                  .Select(s => s[random.Next(s.Length)])
                  .ToArray());

    return result;
}

public static string GenerateAlphaNumericCode(int length)
{
    string newcode = string.Empty;
    try
    {
        newcode = GenerateCode(length);
        while (!IsAlphaNumeric(newcode))
        {
            newcode = GenerateCode(length);
        }
    }
    catch (Exception)
    {
        throw;
    }

    return newcode;
}

public static bool IsAlphaNumeric(string str)
{
    bool isAlphaNumeric = false;
    Regex reg = new Regex("[0-9A-Z]+");
    isAlphaNumeric = reg.IsMatch(str);
    return isAlphaNumeric;
}

Спасибо всем за ваши идеи.

Ответы [ 6 ]

6 голосов
/ 26 июля 2011

Если вы хотите придерживаться Guid в качестве генератора, вы всегда можете проверить с помощью Regex. Это вернет true, только если присутствует хотя бы одна альфа

Regex reg = new Regex("[a-zA-Z]+");

Затем просто используйте метод IsMatch дляпосмотрите, является ли ваша строка действительной

Таким образом, вам не нужна попытка (ИМХО довольно уродливая). Обойдите вокруг Convert.

Обновление: я вижу ваш последующий комментарий о том, как сделатькод медленнее.Вы создаете экземпляр объекта Regex только один раз или каждый раз, когда выполняется тест?Если последнее, то это будет довольно неэффективно, и вам следует рассмотреть возможность использования в вашем классе свойства «lazy -loaded», например,

    private Regex reg;

    private Regex AlphaRegex
    {
        get
        {
            if (reg == null) reg = new Regex("[a-zA-Z]+");
            return reg;
        }
    }

. Затем просто используйте AlphaRegex.IsMatch () в вашем методе.Я ожидаю, что это изменит ситуацию.

5 голосов
/ 04 апреля 2014

использовать пространство имен, затем использовать System.Linq; используйте нормальную строку проверьте, состоит ли строка как минимум из одного символа или числа.

using System.Linq; 

string StrCheck = "abcd123";
check the string has characters --->  StrCheck.Any(char.IsLetter) 

check the string has numbers   --->   StrCheck.Any(char.IsDigit)

if (StrCheck.Any(char.IsLetter) && StrCheck.Any(char.IsDigit))
{
//statement goes here.....
}

sorry for the late reply ...
2 голосов
/ 26 июля 2011

Как минимум один или один конкретно?

Как я могу генерировать случайные буквенно-цифровые строки в C #?

Множество решений в этом вопросе.Вы можете настроить длину по мере необходимости.

2 голосов
/ 26 июля 2011

Я не совсем понял, что вы хотите в строке, кроме букв (abc и т. Д.) - скажем, числа.
Вы можете сгенерировать случайный символ следующим образом:

Random r = new Random();
r.Next('a', 'z'); //For lowercase
r.Next('A', 'Z'); //For capitals
//or you can convert lowercase to capital:
char c = 'k' + ('A' - 'a');


Если вы хотите создать строку:

var s = new StringBuilder();
for(int i = 0; i < length; ++i)
    s.Append((char)r.Next('a', 'z' + 1)); //Changed to char
return s.ToString(); 


Примечание: я не очень хорошо знаю ASP.NET, поэтому я просто веду себя так, как будто это C #.

1 голос
/ 26 июля 2011

Чтобы ответить на ваш вопрос строго, используя существующий код: есть проблема с вашей логикой рекурсии, которую можно избежать, если не использовать рекурсию ( абсолютно нет причин использовать рекурсию в GenerateNonNumericCode ). Сделайте следующее вместо:

    public static string GenerateNonNumericCode(int length)
    {
        string newcode = GenerateCode(length);
        while (IsNumeric(newcode))
        {
            newcode = GenerateCode(length);
        }
        return newcode;
    }

Другие общие замечания

Ваш код очень неэффективен - создание исключений обходится дорого, поэтому использование try / catch в цикле является медленным и бессмысленным. Как и предполагали другие, регулярное выражение имеет больше смысла (System.Text.RegularExpressions пространство имен).

Это проблема с моим кодом или C #?

Если есть сомнения, проблема почти никогда не в C #.

0 голосов
/ 26 июля 2011

Итак, я бы изменил код так:

static Random r = new Random();
public static string GenerateNonNumericCodeFaster(int length) {
    var firstLength = r.Next(0, length - 1);
    var secondLength = length - 1 - firstLength;
    return GenerateCode(firstLength)
         + (char) r.Next((int)'A', (int)'G')
         + GenerateCode(secondLength);
}

Вы можете сохранить функцию GenerateCode как есть. Все остальное вы выбросите. Идея здесь, конечно, заключается в том, что вместо того, чтобы проверять, содержит ли строка буквенный символ, вы просто явно вставляете один из них. В моих тестах использование этого кода могло сгенерировать 10 000 строк по 8 символов за 0,0172963 секунды по сравнению с вашим кодом, который занимает около 52 секунд , Так что, да, это примерно в 3000 раз быстрее:)

...