代码之家  ›  专栏  ›  技术社区  ›  finnw

从带有尾随垃圾的字符串中解析整数

  •  11
  • finnw  · 技术社区  · 16 年前

    我需要解析一个出现在字符串开头的十进制整数。

    小数后可能有尾随垃圾。这需要忽略(即使它包含其他数字。)

    例如

    "1" => 1
    " 42 " => 42
    " 3 -.X.-" => 3
    " 2 3 4 5" => 2
    

    在.NET framework中是否有内置的方法来执行此操作?

    int.TryParse() 这是不合适的。它允许尾随空格,但不允许其他尾随字符。

    10 回复  |  直到 16 年前
        1
  •  17
  •   Yuriy Faktorovich    16 年前
    foreach (var m in Regex.Matches(" 3 - .x. 4", @"\d+"))
    {
        Console.WriteLine(m);
    }
    

    根据评论更新

    我不知道你为什么不喜欢正则表达式,所以我将只发布我认为最短的解决方案。

    Match match = Regex.Match(" 3 - .x. - 4", @"\d+");
    if (match.Success)
        Console.WriteLine(int.Parse(match.Value));
    
        2
  •  24
  •   Donut    16 年前

    可以使用Linq执行此操作,不需要正则表达式:

    public static int GetLeadingInt(string input)
    {
       return Int32.Parse(new string(input.Trim().TakeWhile(c => char.IsDigit(c) || c == '.').ToArray()));
    }
    

    这适用于您提供的所有示例:

    string[] tests = new string[] {
       "1",
       " 42 ",
       " 3 -.X.-",
       " 2 3 4 5"
    };
    
    foreach (string test in tests)
    {
       Console.WriteLine("Result: " + GetLeadingInt(test));
    }
    
        3
  •  6
  •   Jon Skeet    16 年前

    没有标准的.NET方法可以做到这一点-尽管我不会惊讶地发现VB在Microsoft.VisualBasic程序集中有一些东西(它是与.NET一起提供的,所以即使从C#使用它也不是问题)。

    结果是否总是非负面的(这将使事情变得更容易)?

    老实说,正则表达式是这里最简单的选择,但是。。。

    public static string RemoveCruftFromNumber(string text)
    {
        int end = 0;
    
        // First move past leading spaces
        while (end < text.Length && text[end] == ' ')
        {
            end++;
        }
    
        // Now move past digits
        while (end < text.Length && char.IsDigit(text[end]))
        {
            end++;
        }
    
        return text.Substring(0, end);
    }
    

    那你只需要打个电话 int.TryParse RemoveCruftFromNumber (不要忘记,整数可能太大,无法存储在 int

        4
  •  5
  •   Community Mohan Dere    9 年前

    char.IsDigit char.IsNumber see here ).
    如果只想检查数字0到9,可以使用 "0123456789".Contains(c) .

    三个示例实现:

    要删除尾随的非数字字符,请执行以下操作:

    var digits = new string(input.Trim().TakeWhile(c =>
        ("0123456789").Contains(c)
    ).ToArray());
    

    要删除前导非数字字符,请执行以下操作:

    var digits = new string(input.Trim().SkipWhile(c =>
        !("0123456789").Contains(c)
    ).ToArray());
    

    var digits = new string(input.Trim().Where(c =>
        ("0123456789").Contains(c)
    ).ToArray());
    

    当然: int.Parse(digits) int.TryParse(digits, out output)

        5
  •  1
  •   AngryHacker    16 年前
    string s = " 3 -.X.-".Trim();
    string collectedNumber = string.empty;
    int i;
    
    for (x = 0; x < s.length; x++) 
    {
    
      if (int.TryParse(s[x], out i))
         collectedNumber += s[x];
      else
         break;     // not a number - that's it - get out.
    
    } 
    
    if (int.TryParse(collectedNumber, out i))
        Console.WriteLine(i); 
    else
        Console.WriteLine("no number found");
    
        6
  •  1
  •   finnw    16 年前

    这就是我在Java中的实现方式:

    int parseLeadingInt(String input)
    {
        NumberFormat fmt = NumberFormat.getIntegerInstance();
        fmt.setGroupingUsed(false);
        return fmt.parse(input, new ParsePosition(0)).intValue();
    }
    

    int? parseLeadingInt(string input)
    {
        int result = 0;
        Match match = Regex.Match(input, "^[ \t]*\\d+");
        if (match.Success && int.TryParse(match.Value, out result))
        {
            return result;
        }
        return null;
    }
    
        7
  •  1
  •   David R Tribble    10 年前

    这并不能真正回答您的问题(关于内置C#方法),但您可以尝试逐个切掉输入字符串末尾的字符,直到 int.TryParse() 将其作为有效数字接受:

    for (int p = input.Length;  p > 0;  p--)
    {
        int  num;
        if (int.TryParse(input.Substring(0, p), out num))
            return num;
    }
    throw new Exception("Malformed integer: " + input);
    

    当然,如果 input 它很长。

    补遗

    在尝试每次解析之前,切掉右侧的所有非数字/非空格字符,可以加快解析速度:

    for (int p = input.Length;  p > 0;  p--)
    {
        char  ch;
        do
        {
            ch = input[--p];
        } while ((ch < '0'  ||  ch > '9')  &&  ch != ' '  &&  p > 0);
        p++;
    
        int  num;
        if (int.TryParse(input.Substring(0, p), out num))
            return num;
    }
    throw new Exception("Malformed integer: " + input);
    
        8
  •  0
  •   Spidey    16 年前

    也可以加上我的。

            string temp = " 3 .x£";
            string numbersOnly = String.Empty;
            int tempInt;
            for (int i = 0; i < temp.Length; i++)
            {
                if (Int32.TryParse(Convert.ToString(temp[i]), out tempInt))
                {
                    numbersOnly += temp[i];
                }
            }
    
            Int32.TryParse(numbersOnly, out tempInt);
            MessageBox.Show(tempInt.ToString());
    

    该消息框仅用于测试目的,在验证该方法是否有效后将其删除即可。

        9
  •  0
  •   Chris Martin    16 年前

    我不知道为什么在这种情况下你会避免使用正则表达式。

    public static class CharArrayExtensions
    {
        public static IEnumerable<char> FindInteger(this IEnumerable<char> array)
        {
            foreach (var c in array)
            {
                if(char.IsNumber(c))
                    yield return c;
            }
        }
    }
    

    编辑: 对于错误的结果(以及维护开发人员:)也是如此。

    这里有一个修订:

        public static int FindFirstInteger(this IEnumerable<char> array)
        {
            bool foundInteger = false;
            var ints = new List<char>();
    
            foreach (var c in array)
            {
                if(char.IsNumber(c))
                {
                    foundInteger = true;
                    ints.Add(c);
                }
                else
                {
                    if(foundInteger)
                    {
                        break;
                    }
                }
            }
    
            string s = string.Empty;
            ints.ForEach(i => s += i.ToString());
            return int.Parse(s);
        }
    
        10
  •  0
  •   manji    16 年前
        private string GetInt(string s)
        {
            int i = 0;
    
            s = s.Trim();
            while (i<s.Length && char.IsDigit(s[i])) i++;
    
            return s.Substring(0, i);
        }
    
    推荐文章