我知道一些方法来检查字符串是否只包含数字: 正则表达式,int。解析,tryparse,循环等等。
谁能告诉我最快的方法是什么?
我只需要检查值,不需要实际解析它。
通过“数字”,我是指具体的ASCII数字:0 1 2 3 4 5 6 7 8 9。
如果字符串是数字,这个问题与Identify不同,因为这个问题不仅是关于如何识别,而且是关于识别的最快方法是什么。
我知道一些方法来检查字符串是否只包含数字: 正则表达式,int。解析,tryparse,循环等等。
谁能告诉我最快的方法是什么?
我只需要检查值,不需要实际解析它。
通过“数字”,我是指具体的ASCII数字:0 1 2 3 4 5 6 7 8 9。
如果字符串是数字,这个问题与Identify不同,因为这个问题不仅是关于如何识别,而且是关于识别的最快方法是什么。
当前回答
这可能会非常晚!但我相信它会帮助别人,就像它帮助了我一样。
private static bool IsDigitsOnly(string str)
{
return str.All(c => c >= '0' && c <= '9');
}
其他回答
这应该可以工作:
Regex.IsMatch("124", "^[0-9]+$", RegexOptions.Compiled)
int。解析或int。TryParse并不总是有效,因为字符串可能包含int类型所能容纳的更多数字。
如果你要做这个检查不止一次,使用一个编译过的正则表达式是有用的——第一次会花费更多的时间,但之后会更快。
另一种方法!
string str = "12345";
bool containsOnlyDigits = true;
try { if(Convert.ToInt32(str) < 0){ containsOnlyDigits = false; } }
catch { containsOnlyDigits = false; }
在这里,如果Convert.ToInt32(str)语句失败,则字符串不仅仅包含数字。另一种可能性是,如果字符串具有“-12345”,并成功转换为-12345,则会检查转换后的数字是否小于零。
函数的空验证:
public static bool IsDigitsOnly(string str)
{
return !string.IsNullOrEmpty(str) && str.All(char.IsDigit);
}
如果你关心性能,不要使用int型。TryParse或Regex -编写自己的(简单的)函数(下面是DigitsOnly或DigitsOnly2,但不是DigitsOnly3 - LINQ似乎会引起很大的开销)。
另外,要注意int。如果字符串太长,不能“适合”int, TryParse将失败。
这个简单的基准测试…
class Program {
static bool DigitsOnly(string s) {
int len = s.Length;
for (int i = 0; i < len; ++i) {
char c = s[i];
if (c < '0' || c > '9')
return false;
}
return true;
}
static bool DigitsOnly2(string s) {
foreach (char c in s) {
if (c < '0' || c > '9')
return false;
}
return true;
}
static bool DigitsOnly3(string s) {
return s.All(c => c >= '0' && c <= '9');
}
static void Main(string[] args) {
const string s1 = "916734184";
const string s2 = "916734a84";
const int iterations = 1000000;
var sw = new Stopwatch();
sw.Restart();
for (int i = 0 ; i < iterations; ++i) {
bool success = DigitsOnly(s1);
bool failure = DigitsOnly(s2);
}
sw.Stop();
Console.WriteLine(string.Format("DigitsOnly: {0}", sw.Elapsed));
sw.Restart();
for (int i = 0; i < iterations; ++i) {
bool success = DigitsOnly2(s1);
bool failure = DigitsOnly2(s2);
}
sw.Stop();
Console.WriteLine(string.Format("DigitsOnly2: {0}", sw.Elapsed));
sw.Restart();
for (int i = 0; i < iterations; ++i) {
bool success = DigitsOnly3(s1);
bool failure = DigitsOnly3(s2);
}
sw.Stop();
Console.WriteLine(string.Format("DigitsOnly3: {0}", sw.Elapsed));
sw.Restart();
for (int i = 0; i < iterations; ++i) {
int dummy;
bool success = int.TryParse(s1, out dummy);
bool failure = int.TryParse(s2, out dummy);
}
sw.Stop();
Console.WriteLine(string.Format("int.TryParse: {0}", sw.Elapsed));
sw.Restart();
var regex = new Regex("^[0-9]+$", RegexOptions.Compiled);
for (int i = 0; i < iterations; ++i) {
bool success = regex.IsMatch(s1);
bool failure = regex.IsMatch(s2);
}
sw.Stop();
Console.WriteLine(string.Format("Regex.IsMatch: {0}", sw.Elapsed));
}
}
...产生以下结果…
DigitsOnly: 00:00:00.0346094
DigitsOnly2: 00:00:00.0365220
DigitsOnly3: 00:00:00.2669425
int.TryParse: 00:00:00.3405548
Regex.IsMatch: 00:00:00.7017648
如果每个char只使用一个比较,而不是foreach,可以快20%:
bool isDigits(string s)
{
if (s == null || s == "") return false;
for (int i = 0; i < s.Length; i++)
if ((s[i] ^ '0') > 9)
return false;
return true;
}
用于测试的代码(总是配置文件,因为结果取决于硬件、版本、顺序等):
static bool isDigitsFr(string s) { if (s == null || s == "") return false; for (int i = 0; i < s.Length; i++) if (s[i] < '0' || s[i] > '9') return false; return true; }
static bool isDigitsFu(string s) { if (s == null || s == "") return false; for (int i = 0; i < s.Length; i++) if ((uint)(s[i] - '0') > 9) return false; return true; }
static bool isDigitsFx(string s) { if (s == null || s == "") return false; for (int i = 0; i < s.Length; i++) if ((s[i] ^ '0') > 9) return false; return true; }
static bool isDigitsEr(string s) { if (s == null || s == "") return false; foreach (char c in s) if (c < '0' || c > '9') return false; return true; }
static bool isDigitsEu(string s) { if (s == null || s == "") return false; foreach (char c in s) if ((uint)(c - '0') > 9) return false; return true; }
static bool isDigitsEx(string s) { if (s == null || s == "") return false; foreach (char c in s) if ((c ^ '0') > 9) return false; return true; }
static void test()
{
var w = new Stopwatch(); bool b; var s = int.MaxValue + ""; int r = 12345678*2; var ss = new SortedSet<string>(); //s = string.Concat(Enumerable.Range(0, 127).Select(i => ((char)i ^ '0') < 10 ? 1 : 0));
w.Restart(); for (int i = 0; i < r; i++) b = s.All(char.IsDigit); w.Stop(); ss.Add(w.Elapsed + ".All .IsDigit");
w.Restart(); for (int i = 0; i < r; i++) b = s.All(c => c >= '0' && c <= '9'); w.Stop(); ss.Add(w.Elapsed + ".All <>");
w.Restart(); for (int i = 0; i < r; i++) b = s.All(c => (c ^ '0') < 10); w.Stop(); ss.Add(w.Elapsed + " .All ^");
w.Restart(); for (int i = 0; i < r; i++) b = isDigitsFr(s); w.Stop(); ss.Add(w.Elapsed + " for <>");
w.Restart(); for (int i = 0; i < r; i++) b = isDigitsFu(s); w.Stop(); ss.Add(w.Elapsed + " for -");
w.Restart(); for (int i = 0; i < r; i++) b = isDigitsFx(s); w.Stop(); ss.Add(w.Elapsed + " for ^");
w.Restart(); for (int i = 0; i < r; i++) b = isDigitsEr(s); w.Stop(); ss.Add(w.Elapsed + " foreach <>");
w.Restart(); for (int i = 0; i < r; i++) b = isDigitsEu(s); w.Stop(); ss.Add(w.Elapsed + " foreach -");
w.Restart(); for (int i = 0; i < r; i++) b = isDigitsEx(s); w.Stop(); ss.Add(w.Elapsed + " foreach ^");
MessageBox.Show(string.Join("\n", ss)); return;
}
Intel i5-3470 @ 3.2GHz的结果,VS 2015 .NET 4.6.1发布模式和优化启用:
time method ratio
0.7776 for ^ 1.0000
0.7984 foreach - 1.0268
0.8066 foreach ^ 1.0372
0.8940 for - 1.1497
0.8976 for <> 1.1543
0.9456 foreach <> 1.2160
4.4559 .All <> 5.7303
4.7791 .All ^ 6.1458
4.8539 .All. IsDigit 6.2421
对于任何想要使用较短方法的人,请注意
.All结果为true为空字符串,异常为空字符串 char。IsDigit对于Nd类别中的所有Unicode字符为真 int。TryParse还允许空格和符号字符