如何正确排序 DataTable 的字符串数字列

How to properly sort a string-number column of a DataTable

我正在尝试对字符串数字列进行排序,例如N1、N10、N100、N2,我期待结果 N1、N2、N10、N100,但排序不起作用,我以相同的顺序得到相同的值 N1、N10、N100、N2。

我写了下面的代码。

static class ExtensionMethod
{
    public static DataTable SortAlphaNumeric(this DataTable datatable, string columnName)
    {
        return datatable.AsEnumerable()
                  .OrderBy(r => r.Field<String>(columnName), new CustomComparer())
                  .CopyToDataTable();
    }
}

public class CustomComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        var numberX = Regex.Match(x, @"\d+").Value;
        var numberY = Regex.Match(y, @"\d+").Value;

        var alphaX = Regex.Match(x, @"[^a-z]").Value;
        var alphaY = Regex.Match(y, @"[^a-z]").Value;

        if (alphaX.CompareTo(alphaY) == 0)
            return numberX.CompareTo(numberY);
        else if (alphaX.CompareTo(alphaY) < 0)
            return -1;
        return 1;            
    }
}

// Code example
class TestExample
{
    public void Test()
    {
        var dt = new DataTable();
        dt.Columns.Add("AlphaNumeric", Type.GetType("System.String"));
        var row = dt.NewRow();
        row["AlphaNumeric"] = "N1";
        dt.Rows.Add(row);
        row = dt.NewRow();
        row["AlphaNumeric"] = "N10";
        dt.Rows.Add(row);
        row = dt.NewRow();
        row["AlphaNumeric"] = "N100";
        dt.Rows.Add(row);
        row = dt.NewRow();
        row["AlphaNumeric"] = "N2";
        dt.Rows.Add(row);

        var orderedDt = dt.SortAlphaNumeric("AlphaNumeric");
    }
}

我会使用 (?<alpha>[A-Za-z])(?<number>\d+) 作为正则表达式并比较 alpha(字符串比较),然后,如果相等,int.Parsenumber 并比较它(整数比较)。

这只会执行两次正则表达式而不是四次(可能编译正则表达式并将其放在静态字段中也会使其更快),并且 2 将小于 10 如果你比较实际数字。如果你不解析数字,你可以跳过整个正则表达式,只做一个字符串比较。

比较器的变化:

var numberX = int.Parse(Regex.Match(x, @"\d+").Value);
var numberY = int.Parse(Regex.Match(y, @"\d+").Value);

如果数字 sheme 是确定的(总是一个字符串 + 一个整数),您可以简单地将它们存储在两个单独的字段中(最好回到数据库中。组合键毕竟是一回事)。那么就是"sort by string first, number 2nd".

如果不是,事情就会变得艰难。您想要的是 Windows 对文件进行的非常不寻常的排序。除了自定义正则表达式解决方案(但同样,如果它是确定性的,您可以适当地使用 2 个或更多字段),还有 StrCmpLogicalW。但是那个是非托管的,它的行为在 Windows 之间变化(它是 "canonical" 排序它运行的 Windows,但排序在 Windows 版本之间变化)。