как извлечь десятичное число из строки в c#

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 ответов


небольшое улучшение решения @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
.

попробовать

Regex.Split (sentence, @"[^0-9\.]+")

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

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

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

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

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

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

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

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

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

если вы не хотите соответствовать числам float без ведущие нули (например,.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)

и a демо здесь:

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 demo:

enter image description here

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

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

var results = Regex.Matches(input, @"<PATTERN_HERE>")
        .Cast<Match>()
        .Select(m => m.Value)
        .ToList();

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


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

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

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


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

\d+(\.\d+)?

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

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


кредит для следующего идет в @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;
    }