从字母数字字符串中删除字符的最快方法是什么?
What's the fastest way to remove characters from an alpha-numeric string?
假设我们有以下字符串作为参数传递给下面的函数:
string sString = "S104";
string sString2 = "AS105";
string sString3 = "ASRVT106";
我希望能够从 string
中提取数字以将它们放入 int
变量中。是否有比以下代码更快 and/or 更有效地从字符串中删除字母的方法?:(*这些字符串将在运行时动态填充 - 它们不会在构造时分配值。)
代码:
public GetID(string sCustomTag = null)
{
m_sCustomTag = sCustomTag;
try {
m_lID = Convert.ToInt32(m_sCustomTag); }
catch{
try{
int iSubIndex = 0;
char[] subString = sCustomTag.ToCharArray();
//ITERATE THROUGH THE CHAR ARRAY
for (int i = 0; i < subString.Count(); i++)
{
for (int j = 0; j < 10; j++)
{
if (subString[i] == j)
{
iSubIndex = i;
goto createID;
}
}
}
createID: m_lID = Convert.ToInt32(m_sCustomTag.Substring(iSubIndex));
}
//IF NONE OF THAT WORKS...
catch(Exception e)
{
m_lID = 00000;
throw e;
}
}
}
}
我以前做过这样的事情,但我不确定是否有更有效的方法来做到这一点。如果它一开始只是一个字母,我可以每次都将 subStringIndex
设置为 1,但用户基本上可以输入他们想要的任何内容。通常,它们会被格式化为 LETTER-then-NUMBER 格式,但如果他们不这样做,或者他们想输入多个字母,如 sString2
或 sString3
,那么我需要能够弥补这一点。此外,如果用户输入一些破旧的非传统格式,如 string sString 4 = S51A24;
,是否有办法从字符串中删除任何和所有字母?
我四处寻找,但在 MSDN 或 Google 上找不到任何内容。非常感谢任何帮助或链接!
您可以使用正则表达式。不一定更快,但更简洁
string sString = "S104";
string sString2 = "AS105";
string sString3 = "ASRVT106";
var re = new Regex(@"\d+");
Console.WriteLine(re.Match(sString).Value); // 104
Console.WriteLine(re.Match(sString2).Value); // 105
Console.WriteLine(re.Match(sString3).Value); // 106
您可以使用 Regex
,但这样做可能更快:
public int ExtractInteger(string str)
{
var sb = new StringBuilder();
for (int i = 0; i < str.Length; i++)
if(Char.IsDigit(str[i])) sb.Append(str[i]);
return int.Parse(sb.ToString());
}
您可以使用一些 LINQ 进一步简化,但要牺牲一点性能:
public int ExtractInteger(string str)
{
return int.Parse(new String(str.Where(c=>Char.IsDigit(c)).ToArray()));
}
现在,如果您只想解析 第一个连续数字序列,请改为这样做:
public int ExtractInteger(string str)
{
return int.Parse(new String(str.SkipWhile(c=>!Char.IsDigit(c)).TakeWhile(c=>Char.IsDigit(c)).ToArray()));
}
string removeLetters(string s)
{
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
if (IsEnglishLetter(c))
{
s = s.Remove(i, 1);
}
}
return s;
}
bool IsEnglishLetter(char c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
虽然你问 "what's the fastest way to remove characters..." 你真正想说的是 "how do I create an integer by extracting only the digits from the string"。
根据这个假设,由于抛出异常,您对 Convert.ToInt32
的第一次调用在您有非数字的情况下会很慢。将其更改为
if (int.TryParse(sCustomTag, out m_lID))
return;
然后您可以使用 in-place unsafe iteration of the characters of the string(这使用 fixed
并避免在 ToCharArray()
中复制数据),提取数字,然后转换它们。它避免了 StringBuilder
的分配,并且比通常的方式迭代字符串快一点。
这是一个 copy/paste-able 版本:
public static unsafe int GetNumber(string s)
{
int number;
if (int.TryParse(s, out number))
return number;
int value = 0;
fixed (char* pString = s)
{
var pChar = pString;
for (int i = 0; i != s.Length; i++, pChar++)
{
if (*pChar < '\u0030' || *pChar > '\u0039') continue;
value = value * 10 + *pChar - '\u0030';
}
}
return value;
}
如果您知道数字总是在开头,请将 continue
更改为 break
;如果数字总是在最后,迭代向后,转换每个单独的数字,将该数字乘以 10 的适当次方,然后添加到累加结果(例如,你的最后一个例子是 6 *100 + 0*101 + 1*102) 直到你到达一个非-数字。
最快的是在不删除任何内容的情况下解析字符串:
var s = "S51A24";
int m_lID = 0;
for (int i = 0; i < s.Length; i++)
{
int d = s[i] - '0';
if ((uint)d < 10)
m_lID = m_lID * 10 + d;
}
Debug.Print(m_lID + ""); // 5124
假设我们有以下字符串作为参数传递给下面的函数:
string sString = "S104";
string sString2 = "AS105";
string sString3 = "ASRVT106";
我希望能够从 string
中提取数字以将它们放入 int
变量中。是否有比以下代码更快 and/or 更有效地从字符串中删除字母的方法?:(*这些字符串将在运行时动态填充 - 它们不会在构造时分配值。)
代码:
public GetID(string sCustomTag = null)
{
m_sCustomTag = sCustomTag;
try {
m_lID = Convert.ToInt32(m_sCustomTag); }
catch{
try{
int iSubIndex = 0;
char[] subString = sCustomTag.ToCharArray();
//ITERATE THROUGH THE CHAR ARRAY
for (int i = 0; i < subString.Count(); i++)
{
for (int j = 0; j < 10; j++)
{
if (subString[i] == j)
{
iSubIndex = i;
goto createID;
}
}
}
createID: m_lID = Convert.ToInt32(m_sCustomTag.Substring(iSubIndex));
}
//IF NONE OF THAT WORKS...
catch(Exception e)
{
m_lID = 00000;
throw e;
}
}
}
}
我以前做过这样的事情,但我不确定是否有更有效的方法来做到这一点。如果它一开始只是一个字母,我可以每次都将 subStringIndex
设置为 1,但用户基本上可以输入他们想要的任何内容。通常,它们会被格式化为 LETTER-then-NUMBER 格式,但如果他们不这样做,或者他们想输入多个字母,如 sString2
或 sString3
,那么我需要能够弥补这一点。此外,如果用户输入一些破旧的非传统格式,如 string sString 4 = S51A24;
,是否有办法从字符串中删除任何和所有字母?
我四处寻找,但在 MSDN 或 Google 上找不到任何内容。非常感谢任何帮助或链接!
您可以使用正则表达式。不一定更快,但更简洁
string sString = "S104";
string sString2 = "AS105";
string sString3 = "ASRVT106";
var re = new Regex(@"\d+");
Console.WriteLine(re.Match(sString).Value); // 104
Console.WriteLine(re.Match(sString2).Value); // 105
Console.WriteLine(re.Match(sString3).Value); // 106
您可以使用 Regex
,但这样做可能更快:
public int ExtractInteger(string str)
{
var sb = new StringBuilder();
for (int i = 0; i < str.Length; i++)
if(Char.IsDigit(str[i])) sb.Append(str[i]);
return int.Parse(sb.ToString());
}
您可以使用一些 LINQ 进一步简化,但要牺牲一点性能:
public int ExtractInteger(string str)
{
return int.Parse(new String(str.Where(c=>Char.IsDigit(c)).ToArray()));
}
现在,如果您只想解析 第一个连续数字序列,请改为这样做:
public int ExtractInteger(string str)
{
return int.Parse(new String(str.SkipWhile(c=>!Char.IsDigit(c)).TakeWhile(c=>Char.IsDigit(c)).ToArray()));
}
string removeLetters(string s)
{
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
if (IsEnglishLetter(c))
{
s = s.Remove(i, 1);
}
}
return s;
}
bool IsEnglishLetter(char c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
虽然你问 "what's the fastest way to remove characters..." 你真正想说的是 "how do I create an integer by extracting only the digits from the string"。
根据这个假设,由于抛出异常,您对 Convert.ToInt32
的第一次调用在您有非数字的情况下会很慢。将其更改为
if (int.TryParse(sCustomTag, out m_lID))
return;
然后您可以使用 in-place unsafe iteration of the characters of the string(这使用 fixed
并避免在 ToCharArray()
中复制数据),提取数字,然后转换它们。它避免了 StringBuilder
的分配,并且比通常的方式迭代字符串快一点。
这是一个 copy/paste-able 版本:
public static unsafe int GetNumber(string s)
{
int number;
if (int.TryParse(s, out number))
return number;
int value = 0;
fixed (char* pString = s)
{
var pChar = pString;
for (int i = 0; i != s.Length; i++, pChar++)
{
if (*pChar < '\u0030' || *pChar > '\u0039') continue;
value = value * 10 + *pChar - '\u0030';
}
}
return value;
}
如果您知道数字总是在开头,请将 continue
更改为 break
;如果数字总是在最后,迭代向后,转换每个单独的数字,将该数字乘以 10 的适当次方,然后添加到累加结果(例如,你的最后一个例子是 6 *100 + 0*101 + 1*102) 直到你到达一个非-数字。
最快的是在不删除任何内容的情况下解析字符串:
var s = "S51A24";
int m_lID = 0;
for (int i = 0; i < s.Length; i++)
{
int d = s[i] - '0';
if ((uint)d < 10)
m_lID = m_lID * 10 + d;
}
Debug.Print(m_lID + ""); // 5124