如何使用C#以数字方式对值进行排序?

Tar*_*zan 10 .net c# sorting string numbers

我有一个字符串,其中包含以句点分隔的数字.当我排序时它看起来像这样,因为它是一个字符串:(ascii char order)

3.9.5.2.1.1
3.9.5.2.1.10
3.9.5.2.1.11
3.9.5.2.1.12
3.9.5.2.1.2
3.9.5.2.1.3
3.9.5.2.1.4
Run Code Online (Sandbox Code Playgroud)

等等

我希望它像这样排序:(按数字顺序)

3.9.5.2.1.1
3.9.5.2.1.2
3.9.5.2.1.3
...
3.9.5.2.1.9
3.9.5.2.1.10
3.9.5.2.1.11
3.9.5.2.1.12
Run Code Online (Sandbox Code Playgroud)

我知道我可以:

  1. 使用"分割"功能可获取各个数字
  2. 将值放入对象中
  3. 对对象排序

如果重复现有功能,我宁愿避免所有这些工作..net框架中的方法是否已经执行此操作?

VVS*_*VVS 6

这是我的工作解决方案,它也处理格式不正确的字符串(例如包含文本)。

这个想法是获取两个字符串中的第一个数字并比较这些数字。如果它们匹配,则继续下一个数字。如果他们不这样做,我们就有一个赢家。如果这些数字根本不是数字,则对尚未比较的部分进行字符串比较。

通过改变确定下一个数字的方式,可以很容易地使比较器完全兼容自然排序顺序。

看那个..刚发现这个问题

比较器:

class StringNumberComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        int compareResult;
        int xIndex = 0, yIndex = 0;
        int xIndexLast = 0, yIndexLast = 0;
        int xNumber, yNumber;
        int xLength = x.Length;
        int yLength = y.Length;

        do
        {
            bool xHasNextNumber = TryGetNextNumber(x, ref xIndex, out xNumber);
            bool yHasNextNumber = TryGetNextNumber(y, ref yIndex, out yNumber);

            if (!(xHasNextNumber && yHasNextNumber))
            {
                // At least one the strings has either no more number or contains non-numeric chars
                // In this case do a string comparison of that last part
                return x.Substring(xIndexLast).CompareTo(y.Substring(yIndexLast));
            }

            xIndexLast = xIndex;
            yIndexLast = yIndex;

            compareResult = xNumber.CompareTo(yNumber);
        }
        while (compareResult == 0
            && xIndex < xLength
            && yIndex < yLength);

        return compareResult;
    }

    private bool TryGetNextNumber(string text, ref int startIndex, out int number)
    {
        number = 0;

        int pos = text.IndexOf('.', startIndex);
        if (pos < 0) pos = text.Length;

        if (!int.TryParse(text.Substring(startIndex, pos - startIndex), out number))
            return false;

        startIndex = pos + 1;

        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

public static void Main()
{
    var comparer = new StringNumberComparer();

    List<string> testStrings = new List<string>{
        "3.9.5.2.1.1",
        "3.9.5.2.1.10",
        "3.9.5.2.1.11",
        "3.9.test2",
        "3.9.test",
        "3.9.5.2.1.12",
        "3.9.5.2.1.2",
        "blabla",
        "....",
        "3.9.5.2.1.3",
        "3.9.5.2.1.4"};

    testStrings.Sort(comparer);

    DumpArray(testStrings);

    Console.Read();
}

private static void DumpArray(List<string> values)
{
    foreach (string value in values)
    {
        Console.WriteLine(value);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

....
3.9.5.2.1.1
3.9.5.2.1.2
3.9.5.2.1.3
3.9.5.2.1.4
3.9.5.2.1.10
3.9.5.2.1.11
3.9.5.2.1.12
3.9.test
3.9.test2
blabla
Run Code Online (Sandbox Code Playgroud)