zoukankan      html  css  js  c++  java
  • 文件名智能排序的算法

    在文件夹中,我们经常有类似s_1.txt、s_2.txt、s_10.txt、s_11.txt这样的命名方式,我们期望的排序方式是s_1.txt、s_2.txt、s_10.txt、s_11.txt(Vista & Windows7是这种方式),然而,按照常规的字符串排序算法的到的结果是s_1.txt、s_10.txt、s_11.txt、s_2.txt(Windows XP是这种方式)。

    要实现方式1所需要的智能排序效果,我们的排序算法需要满足如下规则:

    1. 非数字部分按照字符串排序
    2. 数字部分按照大小排序
    3. 规则1的优先级高于规则2的优先级

    这个规则看起来简单,但是实现起来却不是那么容易,因为我们的文件名没有太大的约束,许多文件名时多段式字符串和数字混合在一起的,文件名之间也没有规律可循。由于今天写个小程序的时候需要这种功能,我在网上找了一下,没有什么合适的通用算法,便自己写了一个(实际上写了好几个,这个是最满意的一个)。

    算法的原理很简单。

    1. 将字符串中的数字左侧填充0,变成定长的文件名。
      上述文件被命名为s_01.txt、s_02.txt、s_10.txt、s_11.txt
    2. 将新文件名按照默认字符串排序算法排序

    代码如下:

    static Regex digitRegex = new Regex(@"\d+");
    static string[] SmartSort(IEnumerable<string> files)
    {
        //
    这里只传文件名,以避免不必要的开销,不同的文件夹的文件没有智能排序的必要
        var maxLength = files.Max(file => digitRegex.Matches(file).Cast<Match>().Max(num => num.Length));

        var query = from file in files
                    let sortFile = digitRegex.Replace(file, m => m.Value.PadLeft(maxLength, '0'))
                    orderby sortFile
                    select file;

        return query.ToArray();
    }

    static void Main(string[] args)
    {
        var files = Directory.GetFiles(@"R:\22").Select(i=>Path.GetFileName(i));

        Console.WriteLine(string.Join("\r\n", SmartSort(files)));
    }

    这个算法可用于文件夹或同种类型的文件排序,对于不同的类型的文件的智能排序,还需要在linq查询的时候加上一个分组的功能,这里就懒得写了。

    这个算法谈不上高效(这个算法只用来对一个文件夹下的所有文件排序,实际上也不存在什么效率问题),但却是我尝试的几种算法中最简单的一个,也是我最满意的一个,目前没有发现什么bug,如果谁有更合适的算法,欢迎指教。

  • 相关阅读:
    爱因斯坦IQ题
    微软操作系统的版本分类方法
    C++的辅助工具介绍
    让Dictionary key 支持自定义对象
    正则表达式匹配可能包括任意长度的任意空白的任意字符串(最短匹配)
    linq 对象转换
    "System.Data.SqlServerCe.SqlCeException: 数据库文件大于配置的最大数据库大小。该设置仅在第一次并发数据库连接后生效"解决方案
    Windows XP远程桌面端口更改
    Unicode与UTF8互转(C语言实现)
    VS2005+WinXPDDK+DDKWizard配置驱动开发环境
  • 原文地址:https://www.cnblogs.com/TianFang/p/1617769.html
Copyright © 2011-2022 走看看