按自定义规则对List <string>进行排序

时间:2018-08-16 20:23:27

标签: c# list sorting

我当前正在编写一个程序,该程序读取目录,将目录中所有.pdf文件的路径写入列表,然后将文件合并为单个.pdf文件

public void ProcessFiles(string path)
{
    try
    {
        List<string> pathsForFiles = new List<string>();
        String storeNum = "";
        //Every subdirectory in the directory
        foreach (string d in Directory.GetDirectories(path))
        {
            storeNum = (Path.GetFileName(d));

            //Every item in the folder
            foreach (string filePaths in Directory.GetFiles(d))
            {
                pathsForFiles.Add(filePaths);
            }

            pathsForFiles.Sort(new PdfFileComparer());

            foreach (string f in Directory.GetFiles(d))
            {
                Console.WriteLine(f);
            }

            string dirForOutput = @"C:\Users\EMC\Desktop";
            MergeFiles(pathsForFiles, storeNum, dirForOutput);
            pathsForFiles.Clear();

            Console.WriteLine(" - - - - - - - - - - - - - - - - ");
        }
        Console.ReadKey();
    }
    catch (Exception excpt)
    {
        Console.WriteLine(excpt.Message);
    }
} // end ProcessFiles()

public void MergeFiles(List<string> f, string storeNum, string outputDirectory)
{
    PdfVision v = new PdfVision();
    string[] files = new string[f.Count];
    int i = 0;
    foreach (string s in f)
    {
        files[i] = s;
        i++;
    }
    string outName = outputDirectory + "\\" + storeNum + " Original As-Builts.pdf";
    int ret = v.MergePDFFileArrayToPDFFile(files, @outName);
    //0 - merged successfully
    //1 - error, can't merge PDF documents
    //2 - error, can't create output file, probably it used by another application
    //3 - merging failed
    //4 - merged successfully, but some files were not merged
    Console.WriteLine("Merge Status - " + ret);
}

程序按预期运行,但是.pdf文件不正确。我无法重命名实际文件,但是我需要提出一种对它们进行排序的方法。我对.pdf顺序的指导原则如下-

  1. 封面页面
  2. S-页面
  3. E-页面
  4. L-页面
  5. C-页面
  6. D-页面
  7. 其他(H,R等)

我想出了一个类来编写我的比较,但是它只是稍微地以我想要的方式工作。这是课程,目前它确保COVER页面始终在第一位,但是我不知道从哪里继续。

class PdfFileComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        string file1 = Path.GetFileNameWithoutExtension(x);
        string file2 = Path.GetFileNameWithoutExtension(y);
        // Get last part of filenames (after the last '_')
        string lastBit1 = file1.Substring(file1.LastIndexOf('_') + 1);
        string lastBit2 = file2.Substring(file2.LastIndexOf('_') + 1);

        // Ensure COVER file always first
        if (string.Compare(lastBit1, "COVER", StringComparison.InvariantCultureIgnoreCase) == 0)
        {
            return -1;
        }
        if (string.Compare(lastBit2, "COVER", StringComparison.InvariantCultureIgnoreCase) == 0)
        {
            return 1;
        }

        // Else just sort by the last part alphabetically (ignoring case)
        return String.Compare(lastBit1, lastBit2, StringComparison.CurrentCultureIgnoreCase);
    }
}

我的问题是我如何使此类符合上述文件排序标准。文件的格式看起来像这样,其中结尾表示页面类型。

  

C:\ Users \ Desktop \ PDFs \ T-0023 \ T-0023_H1.pdf

     

C:\ Users \ Desktop \ PDFs \ T-0023 \ T-0023_c3_S01.pdf

     

C:\ Users \ Desktop \ PDFs \ T-0023 \ T-0023_L01.pdf

     

C:\ Users \ Desktop \ PDFs \ T-0023 \ T-0023_H3A.pdf

     

C:\ Users \ Desktop \ PDFs \ T-0023 \ T-0023_H3B.pdf

2 个答案:

答案 0 :(得分:0)

我将按顺序创建所需类型的集合:

require 'yaml'
yml = <<YML
:root:
  :cloud.n2:
    :accessKey: "I5VAJUYNR4AAKIZDH777"
YML
YAML.load(yml)
#=> {:root=>{:"cloud.n2"=>{:accessKey=>"I5VAJUYNR4AAKIZDH777"}}}

EDIT (更新)以更新代码,以说明文件2的字符在集合中,而不是文件1的字符。

答案 1 :(得分:0)

这是另一种类似的方法,您可以保留要订购的商品的列表,然后为每个文件确定“最后一位”是否以列表中的任何商品开头IndexOf代表列表中的FirstOrDefault项,其中项StartsWith就是该字符串。

逻辑是:

  • 如果两个项目的索引相同,则返回其“ lastBit”字符串的比较,如果相同,则使用整个文件名。

  • 如果列表中未包含第一项,则返回1(第一项大于第二项)

  • 如果第二项不在列表中,则返回-1(第一项小于第二项)

  • 最后,返回列表中它们的索引的比较

代码如下:

class PdfFileComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        var first = Path.GetFileNameWithoutExtension(x);
        var second = Path.GetFileNameWithoutExtension(y);

        // Get last part of filenames (after the last '_')
        var lastBit1 = first.Substring(first.LastIndexOf('_') + 1).ToUpper();
        var lastBit2 = second.Substring(second.LastIndexOf('_') + 1).ToUpper();

        var orders = new List<string>
        {
            "COVER", "S", "E", "L", "C", "D"
        };

        var firstIndex = orders.IndexOf(
            orders.FirstOrDefault(sortTerm => lastBit1.StartsWith(sortTerm)));
        var secondIndex = orders.IndexOf(
            orders.FirstOrDefault(sortTerm => lastBit2.StartsWith(sortTerm)));

        if (firstIndex == secondIndex)
        {
            var result = lastBit1.CompareTo(lastBit2);
            if (result == 0) result = x.CompareTo(y);
            return result;
        }

        if (firstIndex < 0)
        {
            return 1;
        }
        if (secondIndex < 0)
        {
            return -1;
        }

        return firstIndex.CompareTo(secondIndex);
    }
}

要进行测试,我只是根据您提供的文件名创建了一个虚拟文件名列表,并以未排序的方式添加了一些文件名:

private static void Main()
{
    var fileNames = new List<string>
    {
        @"C:\Users\Desktop\PDFs\T-0023\T-0023_H1.pdf",
        @"C:\Users\Desktop\PDFs\T - 0023\T - 0023_c3_S01.pdf",
        @"C:\Users\Desktop\PDFs\T - 0023\T - 0023_L01.pdf",
        @"C:\Users\Desktop\PDFs\T - 0023\T - 0023_E3A.pdf",
        @"C:\Users\Desktop\PDFs\T - 0023\T - 0023_H3B.pdf",
        @"C:\Users\Desktop\PDFs\T - 0023\T - 0023_c3_COVER.pdf",
        @"C:\Users\Desktop\PDFs\T - 0023\T - 0023_D3A.pdf",
        @"C:\Users\Desktop\PDFs\T - 0023\T - 0023_C3B.pdf",
    };

    fileNames.Sort(new PdfFileComparer());

    fileNames.ForEach(Console.WriteLine);

    GetKeyFromUser("\nPress any key to exit...");
}

输出

enter image description here