【问题标题】:Get the first numbers from a string从字符串中获取第一个数字
【发布时间】:2015-02-08 14:59:40
【问题描述】:

我想获取字符串中数字的第一个实例。

所以我得到了这个输入字符串,它可能是以下之一:

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.

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

【问题讨论】:

    标签: c# string numbers substring


    【解决方案1】:

    使用Linq的正确方法如下

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

    基本上跳过所有不是数字的内容,然后在不再是数字时停止取字符。请注意,这将在标点符号处停止,因此它不会从字符串中拉出诸如“30.5”之类的内容。如果您需要处理数字中的标点符号,那么正则表达式将是您的选择。另请注意,您不需要执行 ToCharArray,因为 string 实现了 IEnumerable<char>,这就是 Linq 所需要的。

    此外,您还必须以 .Net 4.0 为目标,因为他们添加了 SkipWhileTakeWhile 扩展方法。

    【讨论】:

    • 一个很好的解决方案,它比使用正则表达式稍微快一点。至少这就是我已经测试过的。 +1
    【解决方案2】:
    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
    【解决方案3】:

    使用正则表达式获取结果。

    有关正则表达式的更多详细信息,请参阅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;
    

    【讨论】:

      【解决方案4】:

      在我看来你只需要一个正则表达式:

      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 稍慢(我自己的测试结果)。
      • 此解决方案在标点符号处停止。不能返回“1.5”,而是返回“1”。
      • @n.Stenvang:您的示例代码也是如此。您的问题中的 Nothing 说明了有关非整数的任何信息。性能甚至是这里的一个因素吗?同样,问题中没有任何内容 - 您是否对实际应用程序进行了基准测试,以确定这段代码在大局中是否真的很重要?
      • 我的问题中没有任何内容表明我想返回十进制数字,那是因为我不需要它。但是其他人可能会遇到这个解决方案,我只是想向他们说明它无法返回十进制数字以防万一他们需要它。我没有对我的代码进行基准测试,性能也不是一个因素。我再次声明它有点慢。您的解决方案没有任何问题。它非常适合我需要它做的事情!
      猜你喜欢
      • 1970-01-01
      • 2018-07-11
      • 1970-01-01
      • 2015-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多