Есть ли библиотечная функция, чтобы определить, какая часть строки является числом? - PullRequest
1 голос
/ 17 октября 2019

Существует ли какая-либо библиотечная функция, которая потребляет символы строки и анализирует их как двойные - даже если не вся строка является числом - и возвращает количество использованных символов и проанализированного результата?

Я представляю что-то вроде int ConsumeDouble(string text, out double value). Предположим, у меня есть string s = "12.42;3.14", функция будет читать «12.42», останавливаться на точке с запятой, записывать 12.42 в значение и возвращать 5, потому что она потребляет 5 символов.

Я слабо помню, что что-то подобное существовало в C, но я не могу найти что-то подобное в C #. Существует ли такая функция в структуре dot net? Или есть ли способ достичь этого без написания самого парсера и без регулярных выражений?


Приведенная выше строка s является лишь примером, в моем случае нет четкого указания, где можно ожидать чисел, а где нет.


Если такой функции не существует, чтобудет лучшим способом написать такую ​​функцию? Я подумал о том, чтобы конечный автомат проверял, какие символы принадлежат к числу, а затем использовал double.Parse() для его анализа.

1 Ответ

2 голосов
/ 17 октября 2019

Предполагая, что эффективность не слишком важна, а также предполагая, что вы всегда ожидаете, что число начинается с НАЧАЛА строки, а не частично:

public static (double result, int consumed) ParseLongestNumber(string s)
{
    for (int n = s.Length; n > 0; --n)
    {
        string t = s.Substring(0, n);

        if (double.TryParse(t, out var r))
            return (r, n);
    }

    return (double.NaN, 0);
}

Это должно обрабатывать всечисловые форматы, например, ParseLongestNumber("-1.42e3;3.14") вернет (-1420, 7).

Если число не может быть проанализировано, оно вернет (NaN, 0).

(Примечание. Вы не сказали, чтоИспользовали старую версию C # - если да, вам придется возвращать результаты с помощью параметров out или с помощью экспликации Tuple, а не через кортежи нового стиля.)

ВозможноОптимизация заключается в том, чтобы найти последний возможный числовой символ и проанализировать его только до этого:

public static (double result, int consumed) ParseLongestNumber(string s)
{
    const string NUMBER_CHARS = "+-.,e0123456789";

    int n = 0;

    while (n < s.Length)
        if (NUMBER_CHARS.IndexOf(s[n]) < 0)
            break;
        else
            ++n;

    for (; n > 0; --n)
    {
        string t = s.Substring(0, n);

        if (double.TryParse(t, out var r))
            return (r, n);
    }

    return (double.NaN, 0);
}

Является ли эта опция на самом деле полезной, можно определить только путем эмпирического тестирования.

...