将数值作为字符串进行比较
本文关键字:比较 字符串 | 更新日期: 2023-09-27 18:24:57
我有一个方法,它得到两个字符串。这些字符串可以同时包含数字、ASCII字符或两者。
算法是这样工作的:
- 将两个字符串拆分为字符数组A和B
- 尝试将元素Ai和Bi解析为int
- 比较元素Ai和元素Bi,如果是整数,则使用直接比较,如果是字符,则使用顺序字符串比较
- 根据结果做事
现在,我想知道:我真的需要将元素解析为int吗?我可以简单地比较有序字符串比较中的每个元素,得到相同的结果,对吧?这里的性能含义是什么?解析和正常比较比顺序字符串比较快吗?速度慢吗?
我的假设(使用顺序字符串比较而不是解析和比较)正确吗?
以下是有问题的方法:
internal static int CompareComponentString(this string componentString, string other)
{
bool componentEmpty = string.IsNullOrWhiteSpace(componentString);
bool otherEmtpy = string.IsNullOrWhiteSpace(other);
if (componentEmpty && otherEmtpy)
{
return 0;
}
if (componentEmpty)
{
return -1;
}
if (otherEmtpy)
{
return 1;
}
string[] componentParts = componentString.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
string[] otherParts = other.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < Math.Min(componentParts.Length, otherParts.Length); i++)
{
string componentChar = componentParts[i];
string otherChar = otherParts[i];
int componentNumVal, otherNumVal;
bool componentIsNum = int.TryParse(componentChar, out componentNumVal);
bool otherIsNum = int.TryParse(otherChar, out otherNumVal);
if (componentIsNum && otherIsNum)
{
if (componentNumVal.CompareTo(otherNumVal) == 0)
{
continue;
}
return componentNumVal.CompareTo(otherNumVal);
}
else
{
if (componentIsNum)
{
return -1;
}
if (otherIsNum)
{
return 1;
}
int comp = string.Compare(componentChar, otherChar, StringComparison.OrdinalIgnoreCase);
if (comp != 0)
{
return comp;
}
}
}
return componentParts.Length.CompareTo(otherParts.Length);
}
这是可能使用的字符串。我可能只添加部分,在之后使用减号。
- 1.0.0-alpha
- 1.0.0-α1
- 1.0.0-alpha.beta
- 1.0.0-测试版2
使用此方法,您可以为每个字符串创建一个比较字符串。这些字符串可以通过简单的字母数字比较进行比较。
假设:
- 字符串中有一个分隔公共部分和独立部分的减号
- 在之前,减号总是三个整数值除以一个点的子字符串
- 这些整数值不高于999(查看变量"MaxWidth1")
- 后面的减号是另一个子串,由几个部分组成,也被一个点分割
- 第二个子字符串的部分可以是数字或字母数字,最大宽度为7(参见"MaxWidth2")
- 第二个子字符串最多由5部分组成(MaxIndivParts)
把这种方法放在你想放的地方:
public string VersionNumberCompareString(string versionNumber, int MaxWidth1=3, int MaxWidth2=7,int MaxIndivParts=5){
string result = null;
int posMinus = versionNumber.IndexOf('-');
string part1 = versionNumber.Substring(0, posMinus);
string part2 = versionNumber.Substring(posMinus+1);
var integerValues=part1.Split('.');
result = integerValues[0].PadLeft(MaxWidth1, '0');
result += integerValues[1].PadLeft(MaxWidth1, '0');
result += integerValues[2].PadLeft(MaxWidth1, '0');
var alphaValues = part2.Split('.');
for (int i = 0; i < MaxIndivParts;i++ ) {
if (i <= alphaValues.GetUpperBound(0)) {
var s = alphaValues[i];
int casted;
if (int.TryParse(s, out casted)) //if int: treat as number
result += casted.ToString().PadLeft(MaxWidth2, '0');
else //treat as string
result += s.PadRight(MaxWidth2, ' ');
}
else
result += new string(' ', MaxWidth2);
}
return result; }
你这样称呼它:
var s1 = VersionNumberCompareString("1.3.0-alpha.1.12");
//"001003000alpha 00000010000012 "
var s2 = VersionNumberCompareString("0.11.4-beta");
//"000011004beta "
var s3 = VersionNumberCompareString("2.10.11-beta.2");
//"002010011beta 0000002 "
注意最后的"
符号。所有字符串的长度都相同!
希望这能帮助。。。
这是ascii字符串的.net比较逻辑-
private unsafe static int CompareOrdinalIgnoreCaseHelper(String strA, String strB)
{
Contract.Requires(strA != null);
Contract.Requires(strB != null);
Contract.EndContractBlock();
int length = Math.Min(strA.Length, strB.Length);
fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
{
char* a = ap;
char* b = bp;
while (length != 0)
{
int charA = *a;
int charB = *b;
Contract.Assert((charA | charB) <= 0x7F, "strings have to be ASCII");
// uppercase both chars - notice that we need just one compare per char
if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20;
if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20;
//Return the (case-insensitive) difference between them.
if (charA != charB)
return charA - charB;
// Next char
a++; b++;
length--;
}
return strA.Length - strB.Length;
}
}
话虽如此,除非你有一个严格的性能常数,否则我会说,如果你从已经实现的&经过测试的功能,最好重用它,而不是重新发明轮子。它在实现、单元测试、调试和维护方面节省了大量时间;错误修复时间&有助于保持软件简单。