将数值比较为字符串

时间:2015-11-28 19:49:44

标签: c# string

我有一个获取两个字符串的方法。这些字符串可以同时包含数字,ASCII字符或两者。

算法的工作原理如下:

  1. 将两个字符串拆分为char Arrays A和B.
  2. 尝试将元素A i 和B i 解析为int
  3. 将元素A i 与元素B i 进行比较,如果整数使用直接比较,则在字符使用序数字符串比较的情况下。
  4. 根据结果开展工作
  5. 现在,我想知道:我真的需要将元素解析为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-α
    • 1.0.0-alpha.1
    • 1.0.0-alpha.beta
    • 1.0.0-beta.2

2 个答案:

答案 0 :(得分:0)

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;
        }
    }

话虽如此,除非你有严格的表现,否则,我会说如果你从已经实施的&amp;测试功能,更好地重复使用它,而不是重新发明轮子。 它节省了大量的实施,单元测试,调试和时间。错误修复时间。 &安培;有助于保持软件简单。

答案 1 :(得分:0)

使用此方法,您可以为每个字符串创建比较字符串。这些字符串可通过简单的字母数字比较来比较。

假设:

  • 分隔公共部分和indiv部分的字符串中有一个减号
  • 之前减号总是三个整数值的子串除以点
  • 这些整数值不高于999(查看变量&#34; MaxWidth1&#34;)
  • 背后减号是由多个部分组成的另一个子串,也用点划分
  • 第二个子串的部分可以是数字或字母数字,最大值。宽度为7(查看&#34; MaxWidth2&#34;)
  • 第二个子串由max组成。 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                     "                        

请注意最终的"标志。所有字符串的长度都相同!

希望这会有所帮助......