Как извлечь десятичное число из строки в C # - PullRequest
9 голосов
/ 26 августа 2010
string sentence = "X10 cats, Y20 dogs, 40 fish and 1 programmer.";

 string[] digits = Regex.Split (sentence, @"\D+");

для этого кода я получаю значения в массиве цифр, как этот 10,20,40,1

string sentence = "X10.4 cats, Y20.5 dogs, 40 fish and 1 programmer.";

 string[] digits = Regex.Split (sentence, @"\D+");

для этого кода я получаю значения в массиве цифр, как этот 10,4,20,5,40,1

но я хотел бы получить как это 10,4,20,5,40,1 в десятичных числах, как я могу это сделать.

Ответы [ 7 ]

26 голосов
/ 26 августа 2010

Небольшое улучшение решения @ Michael:

// NOTES: about the LINQ:
// .Where() == filters the IEnumerable (which the array is)
//     (c=>...) is the lambda for dealing with each element of the array
//     where c is an array element.
// .Trim()  == trims all blank spaces at the start and end of the string
var doubleArray = Regex.Split(sentence, @"[^0-9\.]+")
    .Where(c => c != "." && c.Trim() != "");

Возвращает:

10.4
20.5
40
1

Исходное решение возвращалось

[empty line here]
10.4
20.5
40
1
.
8 голосов
/ 29 июня 2017

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

A универсальное регулярное выражение для соответствия наиболее распространенным типам десятичных чисел предоставляется в Сопоставление чисел с плавающей точкой с регулярным выражением :

[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?

Я изменил только группу захвата на группу без захвата (добавлено ?: после (). Это соответствует enter image description here

Если вам нужно сделать его еще более универсальным, , если десятичный разделитель может быть либо точкой, либо запятой , замените \. на класс символов (или выражение в скобках) [.,]:

[-+]?[0-9]*[.,]?[0-9]+(?:[eE][-+]?[0-9]+)?
           ^^^^

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

[-+]?[0-9]*\.[0-9]+(?:[eE][-+]?[0-9]+)?
            ^

Теперь 34 не соответствует: enter image description here соответствует.

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

[-+]?[0-9]+\.[0-9]+(?:[eE][-+]?[0-9]+)?
          ^

См. это демо . Теперь это соответствует гораздо меньшему количеству образцов: enter image description here

А что если вы не хотите совпадать с <digits>.<digits> внутри <digits>.<digits>.<digits>.<digits>? Как сопоставить их как целые слова ? Используйте lookarounds :

[-+]?(?<!\d\.)\b[0-9]+\.[0-9]+(?:[eE][-+]?[0-9]+)?\b(?!\.\d)

И демо здесь :

enter image description here

А как насчет тех чисел с плавающей точкой, которые имеют тысячи разделителей, например 12 123 456.23 или 34,345,767.678? Вы можете добавить (?:[,\s][0-9]+)* после первого [0-9]+, чтобы сопоставить ноль или более последовательностей запятой или пробела, за которыми следуют 1+ цифр:

[-+]?(?<![0-9]\.)\b[0-9]+(?:[,\s][0-9]+)*\.[0-9]+(?:[eE][-+]?[0-9]+)?\b(?!\.[0-9])

См. Демонстрационную версию regex :

enter image description here

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

Теперь, как использовать эти шаблоны в C #?

var results = Regex.Matches(input, @"<PATTERN_HERE>")
        .Cast<Match>()
        .Select(m => m.Value)
        .ToList();
5 голосов
/ 26 августа 2010

попробуй

Regex.Split (sentence, @"[^0-9\.]+")
1 голос
/ 26 августа 2010

Вы должны будете разрешить десятичные разряды в вашем регулярном выражении.Попробуйте следующее:

\d+(\.\d+)?

Это будет совпадать с числами, а не со всеми, кроме чисел, но для создания массива должно быть просто выполнять итерации по матчам.

Что-то для сохраненияИмеется в виду, следует ли вам искать отрицательные знаки, запятые и т. д.

1 голос
/ 26 августа 2010

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

0 голосов
/ 13 июня 2018

Кредит на следующее идет к @ code4life. Все, что я добавил, это цикл for для анализа целых / десятичных чисел перед возвратом.

    public string[] ExtractNumbersFromString(string input)
    {
        input = input.Replace(",", string.Empty);

        var numbers =  Regex.Split(input, @"[^0-9\.]+").Where(c => !String.IsNullOrEmpty(c) && c != ".").ToArray();

        for (int i = 0; i < numbers.Length; i++)
            numbers[i] = decimal.Parse(numbers[i]).ToString();

        return numbers;
    }
0 голосов
/ 26 августа 2010

Если у вас есть Linq:

stringArray.Select(s=>decimal.Parse(s));

A foreach также будет работать. Возможно, вам придется проверить, что каждый string на самом деле является числом (.Parse не вызывает исключение).

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