如何从C#中的字符串中提取十进制数

Posted

技术标签:

【中文标题】如何从C#中的字符串中提取十进制数【英文标题】:How to extract decimal number from string in C# 【发布时间】:2011-04-04 06:29:56 【问题描述】:
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 作为十进制数。我怎样才能做到这一点?

【问题讨论】:

我喜欢他使用dotnetperls.com/regex-split这个非常精确的例子 @Wildhorn - 这有什么问题?他可能在寻找问题的答案时发现了它,并注意到它很接近,但还不够接近。 【参考方案1】:

@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
.

【讨论】:

.Where (w => !String.IsNullOrEmpty(w)) 更优雅。 (>= .net 4) @kami:那是因为正则表达式只寻找正数。您必须根据您的情况修改正则表达式。但是,我的回答专门(7 年前)旨在解决 OP,并不适用于所有情况。【参考方案2】:

十进制/浮点数提取正则表达式可能会有所不同,具体取决于是否使用千位分隔符以及使用的千位分隔符、表示小数分隔符的符号、是否还想匹配指数、是否匹配正号或负号,是否匹配可能省略前导 0 的数字,是否提取以小数分隔符结尾的数字。

Matching Floating Point Numbers with a Regular Expression 中提供了一个通用正则表达式来匹配最常见的十进制数字类型

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

我只是将捕获组更改为非捕获组(在( 之后添加?:)。 It matches

如果您需要使其更加通用,如果小数点分隔符可以是点或逗号,请将 \. 替换为字符类(或括号表达式)[.,]

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

注意上面的表达式匹配整数和浮点数仅匹配浮点数/十进制数通过删除\. 之后的第二个? (demo) 确保小数模式部分是强制性的:

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

现在,34 不匹配: 匹配。

如果您不想匹配不带前导零的浮点数(如 .5,请务必使用第一个数字匹配模式(通过添加 + 量词,以匹配 1 次或多次出现的位数):

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

见this demo。现在,它匹配的样本要少得多:

现在,如果您不想在<digits>.<digits>.<digits>.<digits> 中匹配<digits>.<digits> 怎么办?如何将它们作为整个单词进行匹配?使用lookarounds

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

还有一个demo here:

现在,那些有千位分隔符的浮点数呢,比如12 123 456.2334,345,767.678?您可以在第一个 [0-9]+ 之后添加 (?:[,\s][0-9]+)* 以匹配零个或多个逗号或空格序列,后跟 1 个以上数字:

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

见regex demo:

如果您需要使用逗号作为小数分隔符并使用句点作为千位分隔符,请将逗号与 \. 交换。

现在,如何在 C# 中使用这些模式?

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

【讨论】:

感谢您的回答。这不适用于像“1,000,000.20”或“1.000.000,20”这样的字符串。 @joanfihu 它works for 1,000,000.20, but certainly not for 1.000.000,20 因为它们不应该在同一个上下文中使用,因为第二个不遵循美国数字格式。您需要手动更改表达式以使用句点作为数字分组符号和逗号作为小数分隔符。 谢谢。第一个示例确实适用于最后一个正则表达式。我使用了与逗号和点一起使用的那个。你会用什么来检测数字格式?我需要它在美国和英国格式以及世界其他地区工作。 @joanfihu 尝试 ORing 全部 - see this demo。请注意,如果您不必连续匹配数字,即如果您的文本是干净的并且数字没有相互跟随(在逗号或点之后),则可能会更容易,例如\d[\d.,]*(?:[eE][-+]?\d+)?。如有必要,用单词边界括起来。【参考方案3】:

试试

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

【讨论】:

这也会让您误报 10.1.1.4 的值。 插入符号 (^) 不是否定这个吗? @Daren Thomas,\D 等于 [^0-9] @Joel Etherton,是的,它也会匹配像'10.1.1.4'这样的字符串,甚至是单点。 @Daren Thomas,您将句子拆分为一系列非数字字符,只留下数字。【参考方案4】:

您需要在正则表达式中允许小数位。请尝试以下操作:

\d+(\.\d+)?

这将匹配数字而不是数字以外的所有内容,但迭代匹配项以构建数组应该很简单。

要记住的是,您是否还应该寻找负号、逗号等。

【讨论】:

【参考方案5】:

检查大多数编程语言的语法词法分析器以获取小数的正则表达式。 将该正则表达式与字符串匹配,找到所有匹配项。

【讨论】:

【参考方案6】:

如果你有 Linq:

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

foreach 也可以。您可能需要检查每个 string 是否实际上是一个数字(.Parse 不会引发异常)。

【讨论】:

s 是 Linq 查询的范围内变量。这类似于说 foreach(string s in stringArray)。【参考方案7】:

以下归功于@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;
    

【讨论】:

以上是关于如何从C#中的字符串中提取十进制数的主要内容,如果未能解决你的问题,请参考以下文章

c语言中如何提取二进制数中的某一位?

从char数组中提取十六进制数[关闭]

C语言实现字符串中(10进制和16进制)转成十进制数

正整数提取

在 C# 中格式化十进制数

对十进制数使用自定义字符串格式c#