好的,所以我有一长串数字,但我需要确保它没有任何数字,最简单的方法是什么?
5 回答
扫描字符串,测试字符...s.All(c => Char.IsDigit(c))
Enumerable.All 将在找到非数字字符后立即退出。IsDigit 在检查字符方面非常快。成本是 O(N)(尽可能好);当然,这比尝试解析字符串(如果字符串真的很长,这将失败)或使用正则表达式更好......
如果您尝试此解决方案并发现它对您来说太慢了,您可以随时返回良好的旧循环来扫描字符串。
foreach (char c in s) {
if (!Char.IsDigit(c))
return false;
}
return true;
甚至更好:
for (int i = 0; i < s.Length; i++){
if (!Char.IsDigit(s[i]))
return false;
}
return true;
编辑:基准,终于!
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
namespace FindTest
{
class Program
{
const int Iterations = 1000;
static string TestData;
static Regex regex;
static bool ValidResult = false;
static void Test(Func<string, bool> function)
{
Console.Write("{0}... ", function.Method.Name);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
bool result = function(TestData);
if (result != ValidResult)
{
throw new Exception("Bad result: " + result);
}
}
sw.Stop();
Console.WriteLine(" {0}ms", sw.ElapsedMilliseconds);
GC.Collect();
}
static void InitializeTestDataEnd(int length)
{
TestData = new string(Enumerable.Repeat('1', length - 1).ToArray()) + "A";
}
static void InitializeTestDataStart(int length)
{
TestData = "A" + new string(Enumerable.Repeat('1', length - 1).ToArray());
}
static void InitializeTestDataMid(int length)
{
TestData = new string(Enumerable.Repeat('1', length / 2).ToArray()) + "A" + new string(Enumerable.Repeat('1', length / 2 - 1).ToArray());
}
static void InitializeTestDataPositive(int length)
{
TestData = new string(Enumerable.Repeat('1', length).ToArray());
}
static bool LinqScan(string s)
{
return s.All(Char.IsDigit);
}
static bool ForeachScan(string s)
{
foreach (char c in s)
{
if (!Char.IsDigit(c))
return false;
}
return true;
}
static bool ForScan(string s)
{
for (int i = 0; i < s.Length; i++)
{
if (!Char.IsDigit(s[i]))
return false;
}
return true;
}
static bool Regexp(string s)
{
// String contains numbers
return regex.IsMatch(s);
// String contains letters
//return Regex.IsMatch(s, "\\w", RegexOptions.Compiled);
}
static void Main(string[] args)
{
regex = new Regex(@"^\d+$", RegexOptions.Compiled);
Console.WriteLine("Positive (all digitis)");
InitializeTestDataPositive(100000);
ValidResult = true;
Test(LinqScan);
Test(ForeachScan);
Test(ForScan);
Test(Regexp);
Console.WriteLine("Negative (char at beginning)");
InitializeTestDataStart(100000);
ValidResult = false;
Test(LinqScan);
Test(ForeachScan);
Test(ForScan);
Test(Regexp);
Console.WriteLine("Negative (char at end)");
InitializeTestDataEnd(100000);
ValidResult = false;
Test(LinqScan);
Test(ForeachScan);
Test(ForScan);
Test(Regexp);
Console.WriteLine("Negative (char in middle)");
InitializeTestDataMid(100000);
ValidResult = false;
Test(LinqScan);
Test(ForeachScan);
Test(ForScan);
Test(Regexp);
Console.WriteLine("Done");
}
}
}
我测试了阳性和三个阴性,以 1)测试哪个正则表达式是正确的,2)寻找我的嫌疑人的确认......
我的观点是Regexp.IsMatch
必须扫描字符串,所以它似乎是:时间与扫描一致,只差 3 倍:
Positive (all digitis)
LinqScan... 952ms
ForeachScan... 1043ms
ForScan... 869ms
Regexp... 3074ms
Negative (char at beginning)
LinqScan... 0ms
ForeachScan... 0ms
ForScan... 0ms
Regexp... 0ms
Negative (char at end)
LinqScan... 921ms
ForeachScan... 958ms
ForScan... 867ms
Regexp... 3986ms
Negative (char in middle)
LinqScan... 455ms
ForeachScan... 476ms
ForScan... 430ms
Regexp... 1982ms
致谢:我从 Jon Skeet 那里借用了 Test 函数
结论:s.All(Char.IsDigit)
高效,而且非常容易(毕竟这是最初的问题)。就我个人而言,我发现它比正则表达式更容易(我不得不查看正确的 SO,因为我不熟悉 C# regexp 语法——这是标准的,但我不知道——而且建议的解决方案是错误的) . 所以.. 衡量一下,不要相信“LINQ 很慢”或“RegExp 很慢”之类的神话。毕竟,它们都可以完成任务(这实际上取决于您需要它的用途),选择您喜欢的那个。
你可以使用char.IsDigit
:
var containsOnlyDigits = "007".All(char.IsDigit); // true
您可以使用IndexOfAny
bool containsDigits = mystring.IndexOfAny("0123456789".ToCharArray()) != -1;
在 Linq 中,你必须这样做:
bool containsDigits = mystring.Any(char.IsDigit);
编辑:
我对此进行了计时,结果发现 Linq 解决方案更慢。
对于长度为 1,000,000 的字符串,linq 解决方案的执行时间约为 13 毫秒,而IndexOfAny
.
对于长度为 10,000,000 的字符串,Linq 的执行时间仍为 ~122ms,而IndexOfAny
为 ~18ms。
使用正则表达式:
using System.Text.RegularExpressions;
string myString = "some long characters...";
if(Regex.IsMatch(myString, @"^\d+$", RegexOptions.Compiled))
{
// String contains only numbers
}
if(Regex.IsMatch(myString, @"^\w+$", RegexOptions.Compiled))
{
// String contains only letters
}
尝试使用TryParse
bool longStringisInt = Int64.TryParse(longString, out number);
如果字符串(即 longString)不能转换为 int(即其中包含字母),则 bool 为 false,否则为 true。
编辑:更改为 Int64 以确保更广泛的覆盖范围