2013-05-15 123 views
-5

好吧,我有一长串数字,但我需要确保它没有任何数字,最简单的方法是什么?c#如何检查一个Long字符串是否包含任何字母?

+2

正则表达式。 – timmy

+1

*编译*正则表达式。 – qJake

+8

你需要开始保持一致 - 你在找字母还是数字?你的头衔和身体不同。另外,如果你有“一长串数字”,但你“需要确保它没有任何数字”,这听起来像是一个问题。提问时注意细节很重要。 –

回答

0

使用正则表达式:

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 
} 
+0

我认为你的正则表达式并不需要..它至少应该是''\\ d“'或'@”\ d“',但更好的是它应该像这个答案一样http:// stackoverflow.com/a/273144/863564,或者它会匹配任何有数字的字符串。 –

+0

当时,OP的问题非常模糊,所以我的回答与此问题相符。我解决了一些问题。 – qJake

3

你可以使用char.IsDigit

var containsOnlyDigits = "007".All(char.IsDigit); // true 
+0

他提到这个字符串很长...... LINQ在这些类型的东西上效率极低。 – qJake

+0

@SpikeX我不这么认为..它肯定比正则表达式更好,而且比解析它更好! –

+0

@SpikeX此外,它会快速失败...... –

0

尝试使用TryParse

bool longStringisInt = Int64.TryParse(longString, out number); 

如果字符串(即longString)不能转换为int (即有字母),那么bool就是假的,否则就是真的。

编辑:更改为Int64的,以确保覆盖范围更广

+1

不是很可靠,对于2147483647以上的任何东西都会失败。如果您使用这种方法,最好使用“Int64.TryParse”。 – James

+0

@詹姆斯 - 真实的,但假设(也许是错误的),我们正在处理较小的数字。编辑答案包括你的建议。 –

3

扫描线,测试字符...为它找到一个非数字characted 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 

学分:我从乔恩斯基特

借来的测试功能

结论:s.All(Char.IsDigit)是有效的,而且非常容易(毕竟这是最初的问题)。就我个人而言,我发现它比正则表达式更容易(我必须看看SO是否是正确的,因为我不熟悉C#regexp语法 - 这是标准的,但我不知道 - 并且提出的解决方案是错误的) 。 所以..测量,不要相信“LINQ很慢”或“RegExp很慢”等神话。 毕竟,他们都可以完成任务(这取决于你需要什么),选择一个你喜欢的。

+0

你可能是指Char.IsDigit(c)。不过,这是他们所有人中最快的解决方案。 – Candide

+0

@Candide ops,我忘了Char是静态的..谢谢!我将编辑我的答案 –

+0

最后一次尝试:我用'(c < '0' || c >'9')替换了'Char.IsDigit';它没有区别(IsDigit是一样好,它得到) –

0

您可以使用IndexOfAny

bool containsDigits = mystring.IndexOfAny("".ToCharArray()) != -1; 

在LINQ你不得不做的事:

bool containsDigits = mystring.Any(char.IsDigit); 

编辑:

我计时这个和原来的LINQ的解决方案是

对于字符串长度1,000,000,linq解决方案的执行时间为〜13ms,IndexOfAny为1ms。
对于字符串长度10,000,000,Linq的执行时间仍然是〜122ms,而IndexOfAny是~18ms。

+0

不错的解决方案!很想看看它是如何比较扫描字符串和使用“IsDigit”,性能明智.. –

+0

谢谢你的基准!我期望一个for()循环稍微快一点,但LINQ并不糟糕.. :) –

+0

@ dema80我站好了。我正在用'All'测试linq解决方案,这是不正确的。要检查是否有一个数字,你必须使用上面的'Any'。所以,是的,linq比较慢。 – Candide

相关问题