如何按数字样式对字符串数组排序

本文关键字:字符串 数组排序 样式 何按 数字 | 更新日期: 2023-09-27 18:02:14

我有一个文件名数组,我想按数字风格排序,请给我一个解决方案。

例二:

原数组:[name99.txt, name98.txt, name100.txt]
排序数组:[name98.txt, name99.txt, name100.txt]
(使用字符串排序,排序结果为[name100.txt, name98.txt, name99.txt])

Example2:

原数组:[a99.txt, b98.txt, b100.txt]
排序数组:[a99.txt, b98.txt, b100.txt]
(使用字符串排序,排序结果为[a99.txt, b100.txt, b99.txt])

如何按数字样式对字符串数组排序

string[] ar = new string[] { "name99.txt", "name98.txt", "name100.txt" };
Array.Sort(ar, (a, b) => int.Parse(Regex.Replace(a, "[^0-9]", "")) - int.Parse(Regex.Replace(b, "[^0-9]", "")));
foreach (var a in ar)
    Console.WriteLine(a);

上面假设您的文件总是被称为name###.txt。对于实际的数值排序,使用以下更复杂的版本:

public static void NumericalSort(string[] ar)
{
    Regex rgx = new Regex("([^0-9]*)([0-9]+)");
    Array.Sort(ar, (a, b) =>
    {
        var ma = rgx.Matches(a);
        var mb = rgx.Matches(b);
        for (int i = 0; i < ma.Count; ++i)
        {
            int ret = ma[i].Groups[1].Value.CompareTo(mb[i].Groups[1].Value);
            if (ret != 0)
                return ret;
            ret = int.Parse(ma[i].Groups[2].Value) - int.Parse(mb[i].Groups[2].Value);
            if (ret != 0)
                return ret;
        }
        return 0;
    });
}
static void Main(string[] args)
{
    string[] ar = new string[] { "a99.txt", "b98.txt", "b100.txt" };
    NumericalSort(ar);
    foreach (var a in ar)
        Console.WriteLine(a);
}

可能有一种管理的方法来做到这一点,但我可能只是p/调用到StrCmpLogicalW

[DllImport("shlwapi.dll", CharSet=CharSet.Unicode, ExactSpelling=true)]
static extern int StrCmpLogicalW(String x, String y);    

如果你使用这个函数,而不是滚动你自己的比较函数,你将得到与使用逻辑比较的资源管理器和其他系统组件相同的行为。

请注意,这将无法在WinAPI不可访问的环境中工作(如Windows Phone, Mono或Silverlight),可能在不同的系统上工作不同,应该用注释修饰,以便将来的代码维护者知道为什么使用p/Invoke进行排序。

可以在这里找到一个解决方案:字母数字排序

当数字块的长度不超过9位时,我的方法很好:

private string[] NumericalSort(IEnumerable<string> list)
{
    var ar = list.ToArray();
    Array.Sort(ar, (a, b) =>
    {
        var aa = Regex.Replace(a, @"'d+", m => m.Value.PadLeft(9, '0'));
        var bb = Regex.Replace(b, @"'d+", m => m.Value.PadLeft(9, '0'));
        
        return string.Compare(aa, bb);
    });
    return ar;
}