Какой самый быстрый способ извлечь 5-значное число из строки в C # - PullRequest
2 голосов
/ 04 ноября 2008

Какой самый быстрый способ извлечь 5-значное число из строки в c #.

У меня есть

string.Join(null, System.Text.RegularExpressions.Regex.Split(expression, "[^\\d]"));

Кто-нибудь еще?

Ответы [ 8 ]

7 голосов
/ 04 ноября 2008

Подход regex, вероятно, самый быстрый для реализации, но не самый быстрый для запуска. Я сравнил простое решение регулярных выражений со следующим кодом ручного поиска и обнаружил, что код ручного поиска в ~ 2x-2.5x быстрее для больших строк ввода и в 4 раза быстрее для маленьких строк:

static string Search(string expression)
{
  int run = 0;
  for (int i = 0; i < expression.Length; i++)
  {
    char c = expression[i];
    if (Char.IsDigit(c))
      run++;
    else if (run == 5)
      return expression.Substring(i - run, run);
    else
      run = 0;
  }
  return null;
}
const string pattern = @"\d{5}";
static string NotCached(string expression)
{
  return Regex.Match(expression, pattern, RegexOptions.Compiled).Value;
}

static Regex regex = new Regex(pattern, RegexOptions.Compiled);
static string Cached(string expression)
{
  return regex.Match(expression).Value;
}

Результаты для строки длиной примерно 50 символов с 5-значной строкой в ​​середине, более 10 ^ 6 итераций, задержка на вызов в микросекундах (меньшее число быстрее):

Простой поиск: 0.648396us

Кэшированное регулярное выражение: 2.1414645us

Регулярное выражение без кэширования: 3.070116us

Результаты для строки ~ 40K с 5-значной строкой посередине в течение 10 ^ 4 итераций, задержка на вызов в микросекундах (меньшее число быстрее):

Простой поиск: 423.801us

Кэшированное регулярное выражение: 1155.3948us

Регулярное выражение без кэширования: 1220.625us

Немного удивительно: я ожидал, что Regex - который компилируется в IL - будет сопоставим с ручным поиском, по крайней мере, для очень больших строк.

6 голосов
/ 04 ноября 2008

Используйте регулярное выражение (\ d {5}), чтобы найти вхождение 5-значного числа в строке, и используйте int.Parse или decimal.Parse для совпадений.

В случае, если в text.

есть только один номер.
int? value = null;
string pat = @"\d{5}"
Regex r = new Regex(pat);
Match m = r.Match(text);
if (m.Success)
{
   value = int.Parse(m.Value);
}
2 голосов
/ 04 ноября 2008

Не используйте регулярные выражения вообще. Это намного мощнее, чем нужно - и эта мощность, вероятно, снизит производительность.

Если вы можете дать более подробную информацию о том, что вам нужно, мы можем написать соответствующий код ... (Контрольные примеры были бы идеальными.)

2 голосов
/ 04 ноября 2008

Вы имеете в виду преобразовать строку в число? Или найти первую 5-значную строку, а затем сделать ее числом? В любом случае, вы, вероятно, будете использовать decimal.Parse или int.Parse.

Я считаю, что регулярные выражения - неправильный подход. Более эффективный подход - просто пройтись по строке в поисках цифры, а затем продвинуться на 4 символа и посмотреть, все ли они цифры. Если они есть, у вас есть подстрока. Нет, он не такой надежный, но у него тоже нет накладных расходов.

1 голос
/ 04 ноября 2008

Если числа существуют с другими символами, регулярные выражения являются хорошим решением.

EG: ([0-9] {5})

будет соответствовать - asdfkki12345afdkjsdl, 12345adfaksk или akdkfa12345

0 голосов
/ 04 ноября 2008

Это может быть быстрее ...

public static string DigitsOnly(string inVal)
        {
            char[] newPhon = new char[inVal.Length];
            int i = 0;
            foreach (char c in inVal)
                if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0)
                    newPhon[i++] = c;
            return newPhon.ToString();
        }

если вы хотите ограничить его максимум пятью цифрами, то

public static string DigitsOnly(string inVal)
        {
            char[] newPhon = new char[inVal.Length];
            int i = 0;
            foreach (char c in inVal)
                if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0 && i < 5)
                    newPhon[i++] = c;
            return newPhon.ToString();
        }
0 голосов
/ 04 ноября 2008

Для большинства строк метод перебора будет быстрее, чем RegEx.

Довольно странный пример:

string strIWantNumFrom = "qweqwe23qeeq3eqqew9qwer0q";

int num = int.Parse(
    string.Join( null, (
        from c in strIWantNumFrom.ToCharArray()
        where c == '1' || c == '2' || c == '3' || c == '4' || c == '5' ||
            c == '6' || c == '7' || c == '8' || c == '9' || c == '0'
        select c.ToString()
    ).ToArray() ) );

Без сомнения, есть гораздо более быстрые способы и множество оптимизаций, которые зависят от точного формата вашей строки.

0 голосов
/ 04 ноября 2008

Если у вас есть простой тестовый пример, такой как «12345» или даже «12345abcd», вообще не используйте regex. Они не известны своей скоростью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...