Natural Sort Order in C#

后端 未结 17 2156
野性不改
野性不改 2020-11-21 04:54

Anyone have a good resource or provide a sample of a natural order sort in C# for an FileInfo array? I am implementing the IComparer interface in

17条回答
  •  春和景丽
    2020-11-21 05:49

    Expanding on a couple of the previous answers and making use of extension methods, I came up with the following that doesn't have the caveats of potential multiple enumerable enumeration, or performance issues concerned with using multiple regex objects, or calling regex needlessly, that being said, it does use ToList(), which can negate the benefits in larger collections.

    The selector supports generic typing to allow any delegate to be assigned, the elements in the source collection are mutated by the selector, then converted to strings with ToString().

        private static readonly Regex _NaturalOrderExpr = new Regex(@"\d+", RegexOptions.Compiled);
    
        public static IEnumerable OrderByNatural(
            this IEnumerable source, Func selector)
        {
            int max = 0;
    
            var selection = source.Select(
                o =>
                {
                    var v = selector(o);
                    var s = v != null ? v.ToString() : String.Empty;
    
                    if (!String.IsNullOrWhiteSpace(s))
                    {
                        var mc = _NaturalOrderExpr.Matches(s);
    
                        if (mc.Count > 0)
                        {
                            max = Math.Max(max, mc.Cast().Max(m => m.Value.Length));
                        }
                    }
    
                    return new
                    {
                        Key = o,
                        Value = s
                    };
                }).ToList();
    
            return
                selection.OrderBy(
                    o =>
                    String.IsNullOrWhiteSpace(o.Value) ? o.Value : _NaturalOrderExpr.Replace(o.Value, m => m.Value.PadLeft(max, '0')))
                         .Select(o => o.Key);
        }
    
        public static IEnumerable OrderByDescendingNatural(
            this IEnumerable source, Func selector)
        {
            int max = 0;
    
            var selection = source.Select(
                o =>
                {
                    var v = selector(o);
                    var s = v != null ? v.ToString() : String.Empty;
    
                    if (!String.IsNullOrWhiteSpace(s))
                    {
                        var mc = _NaturalOrderExpr.Matches(s);
    
                        if (mc.Count > 0)
                        {
                            max = Math.Max(max, mc.Cast().Max(m => m.Value.Length));
                        }
                    }
    
                    return new
                    {
                        Key = o,
                        Value = s
                    };
                }).ToList();
    
            return
                selection.OrderByDescending(
                    o =>
                    String.IsNullOrWhiteSpace(o.Value) ? o.Value : _NaturalOrderExpr.Replace(o.Value, m => m.Value.PadLeft(max, '0')))
                         .Select(o => o.Key);
        }
    

提交回复
热议问题