【发布时间】:2008-11-04 16:56:51
【问题描述】:
在 C# 中从字符串中提取 5 位数字的最快方法是什么。
我有
string.Join(null, System.Text.RegularExpressions.Regex.Split(expression, "[^\\d]"));
还有其他人吗?
【问题讨论】:
-
取决于字符串的格式!里面还有什么?数字可以出现在任何地方..??
在 C# 中从字符串中提取 5 位数字的最快方法是什么。
我有
string.Join(null, System.Text.RegularExpressions.Regex.Split(expression, "[^\\d]"));
还有其他人吗?
【问题讨论】:
正则表达式方法可能是最快实施但不是最快运行的方法。我将一个简单的正则表达式解决方案与以下手动搜索代码进行了比较,发现手动搜索代码对于大输入字符串的速度提高了 ~2x-2.5 倍,对于小字符串来说速度提高了 4 倍:
static string Search(string expression)
{
int run = 0;
for (int i = 0; i < expression.Length; i++)
{
char c = expression[i];
if (Char.IsDigit(c))
run++;
else if (run == 5)
return expression.Substring(i - run, run);
else
run = 0;
}
return null;
}
const string pattern = @"\d{5}";
static string NotCached(string expression)
{
return Regex.Match(expression, pattern, RegexOptions.Compiled).Value;
}
static Regex regex = new Regex(pattern, RegexOptions.Compiled);
static string Cached(string expression)
{
return regex.Match(expression).Value;
}
大约 50 个字符的字符串,中间有一个 5 位数的字符串,超过 10^6 次迭代,每次调用的延迟以微秒为单位(数字越小越快):
简单搜索:0.648396us
缓存的正则表达式:2.1414645us
非缓存正则表达式:3.070116us
在 10^4 次迭代中,中间有一个 5 位字符串的约 40K 字符串的结果,每次调用的延迟以微秒为单位(数字越小越快):
简单搜索:423.801us
缓存的正则表达式:1155.3948us
非缓存正则表达式:1220.625us
有点令人惊讶:我希望 Regex(编译为 IL)与手动搜索相当,至少对于非常大的字符串而言。
【讨论】:
使用正则表达式 (\d{5}) 查找字符串中 5 位数字的出现次数,并对匹配项使用 int.Parse 或 decimal.Parse。
text中只有一个数字的情况。
int? value = null;
string pat = @"\d{5}"
Regex r = new Regex(pat);
Match m = r.Match(text);
if (m.Success)
{
value = int.Parse(m.Value);
}
【讨论】:
您的意思是将字符串转换为数字吗?还是找到前 5 位字符串,然后将其设为数字?无论哪种方式,您都可能会使用 decimal.Parse 或 int.Parse。
我认为正则表达式是错误的方法。一种更有效的方法是简单地遍历字符串寻找一个数字,然后推进 4 个字符并查看它们是否都是数字。如果是的话,你就有了你的子字符串。它没有那么健壮,不,但它也没有开销。
【讨论】:
根本不要使用正则表达式。它比您需要的强大得多 - 而且这种功能可能会影响性能。
如果你能提供更多关于你需要它做什么的细节,我们可以编写适当的代码......(测试用例是理想的。)
【讨论】:
如果数字与其他字符存在正则表达式是一个很好的解决方案。
EG:([0-9]{5})
将匹配 - asdfkki12345afdkjsdl、12345adfaksk 或 akdkfa12345
【讨论】:
如果您有像“12345”甚至“12345abcd”这样的简单测试用例,则根本不要使用正则表达式。他们不以速度着称。
【讨论】:
对于大多数字符串,蛮力方法比 RegEx 更快。
一个相当不错的例子是:
string strIWantNumFrom = "qweqwe23qeeq3eqqew9qwer0q";
int num = int.Parse(
string.Join( null, (
from c in strIWantNumFrom.ToCharArray()
where c == '1' || c == '2' || c == '3' || c == '4' || c == '5' ||
c == '6' || c == '7' || c == '8' || c == '9' || c == '0'
select c.ToString()
).ToArray() ) );
毫无疑问,有很多更快的方法,以及许多取决于字符串的确切格式的优化。
【讨论】:
这可能会更快...
public static string DigitsOnly(string inVal)
{
char[] newPhon = new char[inVal.Length];
int i = 0;
foreach (char c in inVal)
if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0)
newPhon[i++] = c;
return newPhon.ToString();
}
如果你想把它限制在最多五位数,那么
public static string DigitsOnly(string inVal)
{
char[] newPhon = new char[inVal.Length];
int i = 0;
foreach (char c in inVal)
if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0 && i < 5)
newPhon[i++] = c;
return newPhon.ToString();
}
【讨论】: