Разбор числа из строки с не цифрами между - PullRequest
12 голосов
/ 08 июля 2010

Я работаю над проектом .NET и пытаюсь проанализировать только числовое значение из строки.Например,

string s = "12ACD";
int t = someparefun(s); 
print(t) //t should be 12

Допущения пары:

  1. Строковый шаблон всегда будет числом с последующими символами.
  2. Числовая часть всегда будет либо однойили двухзначное значение.

Существует ли какая-либо предопределенная функция C # для анализа числового значения из строки?

Ответы [ 11 ]

29 голосов
/ 08 июля 2010

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

using System;
using System.Text.RegularExpressions;

int result =
    // The Convert (System) class comes in pretty handy every time
    // you want to convert something.
    Convert.ToInt32(
        Regex.Replace(
            "12ACD",  // Our input
            "[^0-9]", // Select everything that is not in the range of 0-9
            ""        // Replace that with an empty string.
    ));

Эта функция выдаст 12 для 12ABC, поэтому, если вам понадобится обрабатывать отрицательные значенияномера, вам нужно другое решение.Это также небезопасно, если вы передадите его только не цифрами, это даст FormatException.Вот некоторые примеры данных:

"12ACD"  =>  12
"12A5"   =>  125
"CA12A"  =>  12
"-12AD"  =>  12
""       =>  FormatException
"AAAA"   =>  FormatException

Немного более многословным, но более безопасным подходом будет использование int.TryParse():

using System;
using System.Text.RegularExpression;

public static int ConvertToInt(String input)
{
    // Replace everything that is no a digit.
    String inputCleaned = Regex.Replace(input, "[^0-9]", "");

    int value = 0;

    // Tries to parse the int, returns false on failure.
    if (int.TryParse(inputCleaned, out value))
    {
        // The result from parsing can be safely returned.
        return value;
    }

    return 0; // Or any other default value.
}

Некоторые примеры данных снова:

"12ACD"  =>  12
"12A5"   =>  125
"CA12A"  =>  12
"-12AD"  =>  12
""       =>  0
"AAAA"   =>  0

Или, если вы хотите, чтобы в строке было только число first , в основном останавливаясь при встрече с чем-то, что не является цифрой, мы внезапно также можем легко обработать отрицательные числа:

using System;
using System.Text.RegularExpression;

public static int ConvertToInt(String input)
{
    // Matches the first numebr with or without leading minus.
    Match match = Regex.Match(input, "-?[0-9]+");

    if (match.Success)
    {
        // No need to TryParse here, the match has to be at least
        // a 1-digit number.
        return int.Parse(match.Value);
    }

    return 0; // Or any other default value.
}

И снова мы проверяем это:

"12ACD"  =>  12
"12A5"   =>  12
"CA12A"  =>  12
"-12AD"  =>  -12
""       =>  0
"AAAA"   =>  0

В целом, если мы говорим о пользовательском вводе, я бы вообще не принял недопустимый ввод, только используя int.TryParse() без некоторыхдополнительная магия и при неудаче информирование пользователя о том, что ввод был неоптимальным (и, возможно, повторный запрос действительного числа).

15 голосов
/ 08 июля 2010

Regex - один из подходов, как продемонстрировал Бобби .

Другой подход, учитывая ваши предположения, заключается в использовании TakeWhile таким образом (с TryParse для дополнительной безопасности):

string input = "12ACD";
string digits = new string(input.TakeWhile(c => Char.IsDigit(c)).ToArray());
int result;
if (Int32.TryParse(digits, out result))
{
    Console.WriteLine(result);
}

Конечно, цель кода не сразу открывается читателю, так как большая часть их времени будет потрачена на расшифровку преобразуемой части TakeWhile в string.

3 голосов
/ 23 ноября 2012

Использование Sprache :

int t = Parse.Number.Select(int.Parse).Parse("12ACD");
print(t) //t should be 12 and type of int32.
3 голосов
/ 08 июля 2010

Метод регулярного выражения, описанный Бобби, вероятно, является лучшим способом справиться с этим, но если вы особенно осторожны с регулярными выражениями, вы можете использовать комбинацию LINQ и метода Convert.ToInt32:

    string test = "12ACD";
    int number = Convert.ToInt32(new String(test.Where(x => char.IsNumber(x)).ToArray()));
0 голосов
/ 08 июля 2010

Как насчет просто:

    public int ReadStartingNumber(string text)
    {
        if (string.IsNullOrEmpty(text) || !char.IsDigit(text[0]))
            throw new FormatException("Text does not start with any digits");

        int result = 0;
        foreach (var digit in text.TakeWhile(c => char.IsDigit(c)))
        {
            result = 10*result + (digit - '0');
        }

        return result;
    }
0 голосов
/ 08 июля 2010

Решение Ahmads привело меня к этому - предполагая, что строка всегда состоит из одного или двух чисел, за которыми следует хотя бы один нецифровый символ:

int number = Int32.Parse(
    Char.IsDigit(foo, 1)  ?  foo.Substring(0, 2)  :  foo.Substring(0, 1), 
    CultureInfo.InvariantCulture);

Логика следующая: если символ в индексе 1 (позиция 2) является цифрой, получить первые два символа, а затем проанализировать их. Если символ в индексе 1 не является цифрой, получите первый символ, а затем проанализируйте его.

0 голосов
/ 08 июля 2010

Даже если бы в CLI была такая встроенная функция;вы либо обнаружите, что он работает только в определенной форме, либо должны указать форму и / или поведение, которое следует использовать с указанной формой.Другими словами, что бы вы хотели, чтобы ваше решение делало с "AB123CD456EF"?Разбирать только первое вхождение, объединять все числовые символы вместе и разбирать это или разбирать каждое вхождение на элемент перечисляемого результата?

В любом из этих случаев вполне адекватно рассматриваются регулярные выражения.Я бы порекомендовал обернуть ваше решение в хорошо читаемые, хорошо документированные функции, в зависимости от того, какие вы выбрали хорошие предложения.

0 голосов
/ 08 июля 2010

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

string s = "13AD";
string s2 = s.Substring(0, s.Length - 2);
int i = int.Parse(s2);

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

0 голосов
/ 08 июля 2010

Поскольку вы знаете, что единственные символы, которые вас интересуют, это либо первые 2, либо только первые, вы можете использовать int.TryParse и SubStringing для первых 2 символов.

Если это возвращает false (то есть 2-йchar не цифра), затем просто выполните int.Parse и Substring на первом символе.

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

0 голосов
/ 08 июля 2010

Int32.Parse()

Есть эквиваленты и для других типов чисел.

Редактировать: после перечитывания я увидел, что ваша строка не только это число. В этом случае вам нужно будет сначала извлечь цифры с помощью регулярного выражения перед использованием parse.

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