如何从字符串中提取所有数字(作为整数)?C#

4

我有一个长字符串,想要遍历它并按顺序提取出所有的整数值。这似乎很简单,但我似乎无法弄清楚。

string raw = "I am a string and I have some numbers 3 45 333 2 39 inside of me 1839 9303, and I'd like to get these numbers into 9 -10 00  9e09 into a string[] or something else";

int[] justNumbers = raw.?????

使用C# .NET 3.5,并在必要时使用Regex和Linq。谢谢。
最终结果将是一个长整型列表。例如:
List<int> numbers = new List<int>();

我最终使用的方法(不是最高效的,但可行)

#region mysolution
        numbers = new List<int>();
        foreach (char item in raw)
        {
            if (item.ToString() == "0")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
            else if (item.ToString() == "1")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
            else if (item.ToString() == "2")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
            else if (item.ToString() == "3")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
            else if (item.ToString() == "4")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
            else if (item.ToString() == "5")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
            else if (item.ToString() == "6")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
            else if (item.ToString() == "7")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
            else if (item.ToString() == "8")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
            else if (item.ToString() == "9")
            {
                numbers.Add(Convert.ToInt32(item.ToString()));
            }
        }

        #endregion

5
预期的最终结果是什么样子?是3、45、333还是3、4、5?或者是其他的东西?需要更详细的信息。 - David Basarab
5个回答

7

以下是大致的代码(未经测试):

var items = raw.Split(' ');
var integers = new List<int>();
foreach(var i in items){
    int test = 0;
    if(int.TryParse(i, out test)){
        integers.add(test);
    }
}
编辑: 有一个TryParse的重载方法,其中参数之一是对System.Globalization.NumberStyles进行按位比较。使用这个重载方法,您可以指定它可以接受哪些类型的整数字符串(AllowExponent是其中之一),因此我想,未经测试9e09应该可以工作。 :) 希望这能帮到你!

这对我的简单问题很有效。我还使用了一系列if/else语句,比较i.ToString == "0",针对每个数字0-9。 - discorax
@discorax 你加了什么代码?请更新你的问题并说明你采用了什么方法——你的评论让我很好奇。 - Michael Haren

6
一种基于正则表达式的方法如下所示:

使用正则表达式的方法如下:

Regex number = new Regex(@"-?\d+");
List<int> ints = number.Matches(raw)
                       .Cast<Match>()
                       .Select(m => Int32.Parse(m.Value))
                       .ToList();

然而,这种方法无法处理9e09,如果它表示9 x 10 ^ 9,则会将其解释为两个单独的数字,分别解析为9和9。


@David Brunelle:这个看起来相当不错:https://dev59.com/ikvSa4cB1Zd3GeqPiOY4 - Michael Haren
1
迈克尔:你能说得更详细一些吗?你觉得不好的是使用正则表达式还是使用LINQ?我对正则表达式的批评表示同情,但另一方面,挑选出可识别的模式,例如数字序列,似乎是工具的典型用法...虽然我总是愿意学习!谢谢! - itowlson
1
@Michael:我认为正则表达式在这里是一个完美的解决方案。每当你需要进行命令或参数解析时,它都非常有用。像regexr.com这样的网站在并行使用时非常棒--它们使测试正则表达式和可视化识别所有匹配组变得超级简单。 - Dave
1
@Michael,我不同意。这个解决方案比答案干净得多,因为如果你理解正则表达式(而且这个并不特别困难),意图非常清晰。 - flq
你可以通过使用TryParse来消除溢出,同时在LINQ语句中,我将其作为独立的答案添加了进去。 - flq
显示剩余10条评论

3
“疯狂”的Linq方式:
    private static IEnumerable<int> GetNumbers(string str)
    {
        foreach (var st in str.Split(new string[]{" "},StringSplitOptions.RemoveEmptyEntries)
            .Where(s => (s.ToCharArray()
                .All(c => Char.IsDigit(c)))))
        {
            yield return Convert.ToInt32(st);
        }
    }

2

回复itowlson,如果有人担心溢出的问题,可以借助临时变量在此情况下使用tryparse:

int tmp = 0;
var result = (from m in new Regex(@"-?\d+").Matches(s).OfType<Match>()
              let doesParse = int.TryParse(m.Value, out tmp)
              where doesParse
              select tmp).ToList();

2
如何呢:
int[] xx = raw.Split( ' ' ).Where( ( s, o ) => Int32.TryParse( s, out o ) ).Select( p => Int32.Parse( p ) ).ToArray();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接