从字符串中获取前面的数字

12

我想要在一个字符串中找到第一个数字的实例。

因此,我有了这个输入字符串,它可能是以下之一:

1: "Event: 1 - Some event"
2: "Event 12 -"
3: "Event: 123"
4: "Event: 12 - Some event 3"

输入字符串的输出必须是:

1: 1
2: 12
3: 123
4: 12

我已经尝试了以下几种方法,但是没有一种可以完全满足我的要求。

number = new String(input.ToCharArray().Where(c => Char.IsDigit(c)).ToArray());
//This gives me all the numbers in the string

var index = input.IndexOfAny("0123456789".ToCharArray());
string substring = input.Substring(index, 4);
number = new string(substring.TakeWhile(char.IsDigit).ToArray());
//This gives me first number and then the numbers in the next 4 characters. However it breaks if there is less than 4 characters after the first number.

编辑:很多人发表了好的解决方案,但我最终接受了我在代码中实际使用的那个。我希望我能接受更多的答案!

4个回答

27

使用Linq正确的方法如下:

number = new string(input.SkipWhile(c=>!char.IsDigit(c))
                         .TakeWhile(c=>char.IsDigit(c))
                         .ToArray());

基本上跳过所有不是数字的字符,然后在不再有数字的时候停止获取字符。请注意,这将停止于标点符号,因此不会从字符串中提取像“30.5”这样的内容。如果您需要处理数字中的标点符号,则正则表达式是解决方法。还要注意,您不需要进行ToCharArray,因为字符串实现了IEnumerable<char>,这就是 Linq 所需的一切。

另外,您需要针对.Net 4.0进行操作,因为那时它们添加了SkipWhileTakeWhile扩展方法。


1
一个好的解决方案,比使用正则表达式稍微快一点。至少我已经测试过了。+1 - n.Stenvang
正则表达式有以下问题:a.速度较慢 b.可能变得过于复杂和难以维护。这是最好的。 - Jason Robertson

10

我认为您只需要一个正则表达式:

using System;
using System.Text.RegularExpressions;

public class Test
{
    static void Main()
    {
        ExtractFirstNumber("Event: 1 - Some event");
        ExtractFirstNumber("Event: 12 -");
        ExtractFirstNumber("Event: 123");
        ExtractFirstNumber("Event: 12 - Some event 3");
        ExtractFirstNumber("Event without a number");
    }

    private static readonly Regex regex = new Regex(@"\d+");
    static void ExtractFirstNumber(string text)
    {
        var match = regex.Match(text);
        Console.WriteLine(match.Success ? match.Value : "No match");
    }
}

第一次匹配仅从第一个数字开始,并在第一个非数字(或字符串的末尾)处停止。如果需要,您可以使用匹配的LengthIndex属性来确定它在字符串中的位置。


一个好的解决方案,能够完成任务。加1。但是这比使用linq略慢(根据我的测试结果)。 - n.Stenvang
这个解决方案在标点处停止。无法返回“1.5”,而是返回“1”。 - n.Stenvang
1
@n.Stenvang:你的示例代码也是如此。你的问题中根本没有提到非整数的情况。性能是否在这里起到了作用?同样,问题中也没有涉及到这一点 - 你是否对实际应用进行过基准测试,以确定这段代码在整体中是否真的很重要? - Jon Skeet
我的问题中没有表明我想要返回十进制数,因为我不需要它。但是其他人可能会遇到这个解决方案,我只是想告诉他们,在需要时它无法返回十进制数。 我还没有对我的代码进行基准测试,性能也不是一个因素。再次强调,我只是说它有点慢。 你的解决方案没有问题。它完全符合我需要它做的事情! - n.Stenvang

3
see if this helps
 var input = "sdmfnasldkfjhasdlfkjh234sdf234234";
        var index = input.IndexOfAny("0123456789".ToCharArray());
        string substring = input.Substring(index); // this will give rest of the string.
        number = new string(substring.TakeWhile(char.IsDigit).ToArray());

        //number will have 234

虽然这不是最好的解决方案,但它确实向 OP 显示了他们在第二次尝试中出错的地方。+1 - juharr

1
使用正则表达式获取结果。
有关正则表达式的更多详细信息,请参阅this
    String s1= "Event: 1 - Some event";
    String s2=  "Event 12 -";
    String s3= "Event: 123";
    String s4=  "Event: 12 - Some event 3";


    String result1 = System.Text.RegularExpressions.Regex.Match(s1, @"\d+").Value;
    String result2 = System.Text.RegularExpressions.Regex.Match(s2, @"\d+").Value;
    String result3 = System.Text.RegularExpressions.Regex.Match(s3, @"\d+").Value;
    String result4 = System.Text.RegularExpressions.Regex.Match(s4, @"\d+").Value;

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