[英]Fastest way to check if string contains only digits in C#
我知道如何檢查字符串是否僅包含數字的幾種方法:
正則表達式、 int.parse
、 tryparse
、循環等。
誰能告訴我最快的檢查方法是什么?
我只需要檢查值,不需要實際解析它。
“數字”是指 ASCII 數字: 0 1 2 3 4 5 6 7 8 9
。
這與Identify if a string is a number不是同一個問題,因為這個問題不僅關於如何識別,而且還關於最快的識別方法是什么。
bool IsDigitsOnly(string str)
{
foreach (char c in str)
{
if (c < '0' || c > '9')
return false;
}
return true;
}
可能是最快的方法。
你可以簡單地使用 LINQ 來做到這一點:
return str.All(char.IsDigit);
.All
對空字符串返回 true,對空字符串拋出異常。char.IsDigit
適用於所有 Unicode 數字字符。以下是基於 1000000 次解析相同字符串的一些基准:
更新release
統計:
IsDigitsOnly: 384588
TryParse: 639583
Regex: 1329571
這是代碼,看起來 IsDigitsOnly 更快:
class Program
{
private static Regex regex = new Regex("^[0-9]+$", RegexOptions.Compiled);
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
string test = int.MaxValue.ToString();
int value;
watch.Start();
for(int i=0; i< 1000000; i++)
{
int.TryParse(test, out value);
}
watch.Stop();
Console.WriteLine("TryParse: "+watch.ElapsedTicks);
watch.Reset();
watch.Start();
for (int i = 0; i < 1000000; i++)
{
IsDigitsOnly(test);
}
watch.Stop();
Console.WriteLine("IsDigitsOnly: " + watch.ElapsedTicks);
watch.Reset();
watch.Start();
for (int i = 0; i < 1000000; i++)
{
regex.IsMatch(test);
}
watch.Stop();
Console.WriteLine("Regex: " + watch.ElapsedTicks);
Console.ReadLine();
}
static bool IsDigitsOnly(string str)
{
foreach (char c in str)
{
if (c < '0' || c > '9')
return false;
}
return true;
}
}
當然,值得注意的是 TryParse 確實允許前導/尾隨空格以及特定於文化的符號。 它也受到字符串長度的限制。
char 已經有一個 IsDigit(char c) 執行此操作:
public static bool IsDigit(char c)
{
if (!char.IsLatin1(c))
return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber;
if ((int) c >= 48)
return (int) c <= 57;
else
return false;
}
你可以簡單地這樣做:
var theString = "839278";
bool digitsOnly = theString.All(char.IsDigit);
通過每個char
和for
而不是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
,空字符串null
異常char.IsDigit
適用 於 Nd 類別中的所有 Unicode 字符int.TryParse
還允許空格和符號字符如果您擔心性能,請不要使用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
具有空驗證的函數:
public static bool IsDigitsOnly(string str)
{
return !string.IsNullOrEmpty(str) && str.All(char.IsDigit);
}
我喜歡 Linq 並讓它在第一次不匹配時退出,你可以這樣做
string str = '0129834X33';
bool isAllDigits = !str.Any( ch=> ch < '0' || ch > '9' );
如果是單個字符串:
if (str.All(Char.IsDigit))
{
// string contains only digits
}
如果它是字符串列表:
if (lstStr.All(s => s.All(Char.IsDigit)))
{
// List of strings contains only digits
}
可能最快的方法是:
myString.All(c => char.IsDigit(c))
注意:如果您的字符串為空且不正確,它將返回True (如果您不將空視為有效數字/數字)
您可以在一行 LINQ 語句中執行此操作。 好的,我意識到這不一定是最快的,所以從技術上講並不能回答這個問題,但它可能是最容易寫的:
str.All(c => c >= '0' && c <= '9')
這應該有效:
Regex.IsMatch("124", "^[0-9]+$", RegexOptions.Compiled)
int.Parse
或int.TryParse
並不總是有效,因為字符串可能包含 int 可以容納的更多數字。
如果您要多次執行此檢查,則使用已編譯的正則表達式很有用 - 第一次需要更多時間,但之后要快得多。
這可能來得太晚了!但我相信它會幫助某人,因為它幫助了我。
private static bool IsDigitsOnly(string str)
{
return str.All(c => c >= '0' && c <= '9');
}
您可以通過使用 C# 中的.IsMatch(string input, string pattern)
方法測試輸入字符串是否只有數字 (0-9) 來嘗試使用正則表達式。
using System;
using System.Text.RegularExpression;
public namespace MyNS
{
public class MyClass
{
public void static Main(string[] args)
{
string input = Console.ReadLine();
bool containsNumber = ContainsOnlyDigits(input);
}
private bool ContainOnlyDigits (string input)
{
bool containsNumbers = true;
if (!Regex.IsMatch(input, @"/d"))
{
containsNumbers = false;
}
return containsNumbers;
}
}
}
問候
這將完美地工作,還有很多其他方法,但這會工作
bool IsDigitsOnly(string str)
{
if (str.Length > 0)//if contains characters
{
foreach (char c in str)//assign character to c
{
if (c < '0' || c > '9')//check if its outside digit range
return false;
}
}else//empty string
{
return false;//empty string
}
return true;//only digits
}
另一種方法!
string str = "12345";
bool containsOnlyDigits = true;
try { if(Convert.ToInt32(str) < 0){ containsOnlyDigits = false; } }
catch { containsOnlyDigits = false; }
在這里,如果語句Convert.ToInt32(str)
失敗,則字符串不只包含數字。 另一種可能性是,如果字符串具有"-12345"
並成功轉換為-12345
,則檢查以驗證轉換的數字不小於零。
我對@TheCodeKing 的回答做了一些小改動。
看起來;
對於 int 類型最快的方法是 TryParse
對於長型,最快的方法是正則表達式。
我的結果如下(打勾)
For int:
TryParse Max: 355788
IsDigitsOnly Max: 787013
Regex Max: 1297691
TryParse Avg: 186007
IsDigitsOnly Avg: 430963
Regex Avg: 464657,79
TryParse Min: 162742
IsDigitsOnly Min: 335646
Regex Min: 452121
For float :
TryParse Max : 3151995
IsDigitsOnly Max: 1392740
Regex Max : 1283451
TryParse Avg: 1391636
IsDigitsOnly Avg: 824029
Regex Avg: 501176
TryParse Min: 1187410
IsDigitsOnly Min: 706646
Regex Min: 476204
長代碼:
using System.Diagnostics;
using System.Text.RegularExpressions;
class Program
{
private static Regex regex = new Regex("^[0-9]+$", RegexOptions.Compiled);
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
watch.Stop();
watch.Reset();
List<TimeSpan> tryparse = new List<TimeSpan>();
List<TimeSpan> isdigitsonly = new List<TimeSpan>();
List<TimeSpan> regexss = new List<TimeSpan>();
for (int say = 0; say < 1000; say++)
{
float value;
string test = Random.Shared.NextInt64(1000,long.MaxValue).ToString();
watch.Start();
for (int i = 0; i < 1000000; i++)
{
float.TryParse(test, out value);
}
watch.Stop();
//Console.WriteLine("TryParse: " + watch.Elapsed);
tryparse.Add(watch.Elapsed);
watch.Reset();
watch.Start();
for (int i = 0; i < 1000000; i++)
{
IsDigitsOnly(test);
}
watch.Stop();
//Console.WriteLine("IsDigitsOnly: " + watch.Elapsed);
isdigitsonly.Add(watch.Elapsed);
watch.Reset();
watch.Start();
for (int i = 0; i < 1000000; i++)
{
regex.IsMatch(test);
}
watch.Stop();
regexss.Add(watch.Elapsed);
watch.Reset();
// Console.WriteLine("Regex: " + watch.Elapsed);
Console.Write("---------------------% " + (Convert.ToDecimal( say)/ 999 * 100).ToString("N2") + "---------------------------");
Console.CursorLeft = 0;
}
Console.WriteLine();
Console.WriteLine($"TryParse: {tryparse.Max(t => t.Ticks)}");
Console.WriteLine($"IsDigitsOnly: {isdigitsonly.Max(t => t.Ticks)}");
Console.WriteLine($"Regex: {regexss.Max(t => t.Ticks)}");
Console.WriteLine();
Console.WriteLine($"TryParse Avg: {tryparse.Average(t => t.Ticks)}");
Console.WriteLine($"IsDigitsOnly Avg: {isdigitsonly.Average(t => t.Ticks)}");
Console.WriteLine($"Regex Avg: {regexss.Average(t => t.Ticks)}");
Console.WriteLine();
Console.WriteLine($"TryParse Min: {tryparse.Min(t => t.Ticks)}");
Console.WriteLine($"IsDigitsOnly Min: {isdigitsonly.Min(t => t.Ticks)}");
Console.WriteLine($"Regex Min: {regexss.Min(t => t.Ticks)}");
Console.ReadLine();
}
static bool IsDigitsOnly(string str)
{
foreach (char c in str)
{
if (c < '0' || c > '9')
return false;
}
return true;
}
}
試試這個代碼:
bool isDigitsOnly(string str)
{
try
{
int number = Convert.ToInt32(str);
return true;
}
catch (Exception)
{
return false;
}
}
char.IsDigit(myChar)
怎么樣?
非常聰明和簡單的方法來檢測你的字符串是否只包含數字是這樣的:
string s = "12fg";
if(s.All(char.IsDigit))
{
return true; // contains only digits
}
else
{
return false; // contains not only digits
}
public bool CheckforDigits(string x)
{
int tr;
return x.All(r=> int.TryParse(r.ToString(), out tr));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.