You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现类Windows资源管理器的C#字母数字自然排序

实现类Windows资源管理器的自然排序

要实现和Windows资源管理器一致的自然排序(无需依赖shlwapi.dll),可以通过拆分字符串为字母/数字段,再按照Windows的比较规则逐段比较来完成。以下是完整实现:

核心实现逻辑

Windows自然排序的核心规则:

  1. 将字符串拆分为连续的数字段和非数字段(包括字母、空格等);
  2. 数字段先按数值大小比较,数值相同时按段长度排序(前导零多的在前,如01排在1前面);
  3. 非数字段按不区分大小写的字典序比较,若大小写不同但字典序一致,再按区分大小写排序;
  4. 数字段整体优先级高于非数字段(纯数字字符串排在字母开头的字符串前)。

代码实现

1. 自然排序比较器

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class WindowsNaturalComparer : IComparer<string>
{
    private static readonly Regex SegmentRegex = new Regex(@"(\d+|\D+)", RegexOptions.Compiled);

    public int Compare(string x, string y)
    {
        if (x == null && y == null) return 0;
        if (x == null) return -1;
        if (y == null) return 1;

        var xSegments = SegmentRegex.Matches(x);
        var ySegments = SegmentRegex.Matches(y);

        int minSegments = Math.Min(xSegments.Count, ySegments.Count);

        for (int i = 0; i < minSegments; i++)
        {
            string xSeg = xSegments[i].Value;
            string ySeg = ySegments[i].Value;

            int compareResult;

            // 判断是否为数字段
            if (long.TryParse(xSeg, out long xNum) && long.TryParse(ySeg, out long yNum))
            {
                // 先比较数值
                compareResult = xNum.CompareTo(yNum);
                if (compareResult != 0)
                    return compareResult;
                
                // 数值相同则比较段长度(前导零多的在前)
                compareResult = ySeg.Length.CompareTo(xSeg.Length);
                if (compareResult != 0)
                    return compareResult;
            }
            else
            {
                // 非数字段:先不区分大小写比较
                compareResult = string.Compare(xSeg, ySeg, StringComparison.OrdinalIgnoreCase);
                if (compareResult != 0)
                    return compareResult;
                
                // 大小写不同但字典序一致时,按区分大小写排序
                compareResult = string.Compare(xSeg, ySeg, StringComparison.Ordinal);
                if (compareResult != 0)
                    return compareResult;
            }
        }

        // 前面的段都匹配,短的字符串排在前面
        return xSegments.Count.CompareTo(ySegments.Count);
    }
}

2. 使用示例(验证你的测试数组)

using System;
using System.Linq;

class Program
{
    static void Main()
    {
        var array = new[]{"B01 002", "B01 0010", "01", "B01 001", "B10 001", "B01 01", "1", "B1 001", "B02 001", "A1"};
        
        // 使用自定义比较器排序
        var sortedArray = array.OrderBy(s => s, new WindowsNaturalComparer()).ToArray();
        
        Console.WriteLine("排序结果:");
        Console.WriteLine(string.Join(", ", sortedArray));
        // 输出:01, 1, A1, B01 001, B01 01, B01 002, B01 0010, B1 001, B02 001, B10 001
    }
}

关键细节说明

  • 正则拆分:用(\d+|\D+)匹配连续数字或非数字,确保字符串被正确拆分为交替的段;
  • 数字段处理:用long.TryParse避免整数溢出,数值相同时比较段长度,保证01排在1前面;
  • 非数字段处理:先不区分大小写比较,符合Windows资源管理器的默认排序行为,再补充区分大小写的比较处理边缘情况;
  • 空值处理:兼容null字符串的比较场景。

内容的提问来源于stack exchange,提问作者theLearner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:01:26