【发布时间】:2010-07-08 14:32:43
【问题描述】:
我正在处理 .NET 项目,我正在尝试仅解析字符串中的数值。例如,
string s = "12ACD";
int t = someparefun(s);
print(t) //t should be 12
几个假设是
- 字符串模式始终是数字后跟字符。
- 数字部分始终为一位或两位数字。
是否有任何 C# 预定义函数来解析字符串中的数值?
【问题讨论】:
标签: c#
我正在处理 .NET 项目,我正在尝试仅解析字符串中的数值。例如,
string s = "12ACD";
int t = someparefun(s);
print(t) //t should be 12
几个假设是
是否有任何 C# 预定义函数来解析字符串中的数值?
【问题讨论】:
标签: c#
没有这样的功能,至少我不知道。但是一种方法是使用正则表达式来删除所有不是数字的内容:
using System;
using System.Text.RegularExpressions;
int result =
// The Convert (System) class comes in pretty handy every time
// you want to convert something.
Convert.ToInt32(
Regex.Replace(
"12ACD", // Our input
"[^0-9]", // Select everything that is not in the range of 0-9
"" // Replace that with an empty string.
));
此函数将为12ABC 生成12,因此如果您需要能够处理负数,则需要不同的解决方案。它也不安全,如果你只传递非数字,它会产生一个FormatException。以下是一些示例数据:
"12ACD" => 12
"12A5" => 125
"CA12A" => 12
"-12AD" => 12
"" => FormatException
"AAAA" => FormatException
更详细但更安全的方法是使用int.TryParse():
using System;
using System.Text.RegularExpression;
public static int ConvertToInt(String input)
{
// Replace everything that is no a digit.
String inputCleaned = Regex.Replace(input, "[^0-9]", "");
int value = 0;
// Tries to parse the int, returns false on failure.
if (int.TryParse(inputCleaned, out value))
{
// The result from parsing can be safely returned.
return value;
}
return 0; // Or any other default value.
}
再来一些示例数据:
"12ACD" => 12
"12A5" => 125
"CA12A" => 12
"-12AD" => 12
"" => 0
"AAAA" => 0
或者如果你只想要字符串中的第一个数字,基本上停在遇到不是数字的东西,我们突然也可以轻松处理负数:
using System;
using System.Text.RegularExpression;
public static int ConvertToInt(String input)
{
// Matches the first numebr with or without leading minus.
Match match = Regex.Match(input, "-?[0-9]+");
if (match.Success)
{
// No need to TryParse here, the match has to be at least
// a 1-digit number.
return int.Parse(match.Value);
}
return 0; // Or any other default value.
}
我们再次对其进行测试:
"12ACD" => 12
"12A5" => 12
"CA12A" => 12
"-12AD" => -12
"" => 0
"AAAA" => 0
总的来说,如果我们谈论的是用户输入,我会考虑根本不接受无效输入,只使用 int.TryParse() 而不使用一些额外的魔法,并且在失败时通知用户输入不是最佳的(并且可能会再次提示输入有效号码)。
【讨论】:
正则表达式是一种方法,如demonstrated by Bobby。
根据您的假设,另一种方法是以这种方式使用TakeWhile(使用TryParse 以提高安全性):
string input = "12ACD";
string digits = new string(input.TakeWhile(c => Char.IsDigit(c)).ToArray());
int result;
if (Int32.TryParse(digits, out result))
{
Console.WriteLine(result);
}
当然,代码的用途不会立即向读者展示,因为他们大部分时间都将花费在破译 TakeWhile 部分被转换为 string 上。
【讨论】:
Int32.TryParse 括在if 中?如果解析失败,原始result 将保持不变。此外,您不应该使用 try catch 吗?因此内置函数TryParse?如果您使用.Parse,那将是有意义的。不过,非常有用的代码。谢谢
TryParse 用于避免显式尝试/捕获。我将它包含在if 中,因为它返回一个布尔值,所以通过使用它,您可以立即知道解析是否成功,并且可以继续使用result。如果您不想依赖默认的 result 解析尝试失败,这将为您提供更多控制。这取决于场景。如果我选择使用 int.Parse,我会使用 try/catch。同样的想法,但TryParse 是为了让我们更具可读性并避免额外的工作。感谢您的评论!
Bobby 描述的正则表达式方法可能是处理这个问题的最佳方法,但如果您对正则表达式特别警惕,您可以结合使用 LINQ 和 Convert.ToInt32 方法:
string test = "12ACD";
int number = Convert.ToInt32(new String(test.Where(x => char.IsNumber(x)).ToArray()));
【讨论】:
ToCharArray 调用是不必要的,因为string 实现了IEnumerable<char>。另外,我可能会选择TakeWhile 而不是Where,这样,例如,“12ACD3”就不会变成“123”。但这显然需要指定。
ToCharArray 来强制它显示在 IntelliSense 中,但没有它也能正常工作。您可能还对这篇文章感兴趣:为什么 VS 2008 不显示 Intellisense for String 类的扩展方法 (stackoverflow.com/questions/345883/…)。
使用Sprache:
int t = Parse.Number.Select(int.Parse).Parse("12ACD");
print(t) //t should be 12 and type of int32.
【讨论】:
由于您知道您关心的唯一字符是前 2 个或只是第一个,因此您可以在前 2 个字符上使用 int.TryParse 和 SubStringing。
如果返回 false(即第二个字符不是数字),那么只需对第一个字符执行 int.Parse 和 Substring ing。
可能有一种更清洁的方法,但根据您的假设,应该可以完成这项工作。
【讨论】:
即使 CLI 中有这样的内在函数;您要么发现它仅适用于特定表单,要么必须告诉它与所述表单一起使用的表单和/或行为。换句话说,您希望您的解决方案如何处理“AB123CD456EF”?仅解析第一次出现,将所有数字字符连接在一起并解析,还是将每次出现解析为可枚举结果的元素?
正则表达式可以很好地处理任何这些情况。我建议您将您的解决方案广泛地包装成可读的、有据可查的函数,无论您选择已经给出的好建议中的哪一个。
【讨论】:
Ahmads 解决方案让我想到了这一点 - 假设字符串始终是一两个数字,后跟至少一个非数字字符:
int number = Int32.Parse(
Char.IsDigit(foo, 1) ? foo.Substring(0, 2) : foo.Substring(0, 1),
CultureInfo.InvariantCulture);
逻辑如下:如果索引 1(位置 2)处的字符是数字,则获取前两个字符,然后解析它们。如果索引 1 处的字符不是数字,则获取第一个字符,然后对其进行解析。
【讨论】:
怎么样:
public int ReadStartingNumber(string text)
{
if (string.IsNullOrEmpty(text) || !char.IsDigit(text[0]))
throw new FormatException("Text does not start with any digits");
int result = 0;
foreach (var digit in text.TakeWhile(c => char.IsDigit(c)))
{
result = 10*result + (digit - '0');
}
return result;
}
【讨论】:
您可以使用 RegEx.Match(正则表达式) 阅读有关它们的 msdn 文章。很简单。
【讨论】:
【讨论】:
根据您的假设,最直接的代码如下...
string s = "13AD";
string s2 = s.Substring(0, s.Length - 2);
int i = int.Parse(s2);
如果您的假设得到保证,这是最易读的方法。不需要正则表达式或花哨的 LINQ 东西。 LINQ 很棒,但它似乎经常被过度使用。
【讨论】:
s.Substring(0, 2);吗?尽管如此,如果只有一位数字,它还是行不通的。 (使用上面的代码,“12ACD”会失败,因为 s.Length-2 是 3 并且 12A 不能解析为 Int32。)
Substring(0,2); 是不够的,因为他可以有一个或两个数字。这部分无法保证。