简体   繁体   English

排序列表 <string> 通过自定义规则

[英]Sorting a List<string> by Custom Rules

I am currently writing a program that reads directories, writes all of the .pdf files' paths in the directory into a List, and merges the files into a single .pdf file 我目前正在编写一个程序,该程序读取目录,将目录中所有.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);
}

The program runs as expected, however the .pdf files are not in order. 该程序将按预期运行,但是.pdf文件不正确。 I cannot rename the actual files, however I need to come up with a way to sort them. 我无法重命名实际文件,但是我需要提出一种对它们进行排序的方法。 My guidelines for the order of the .pdf's are as follows - 我对.pdf的顺序指导如下:

  1. Cover Page 封面
  2. S - Pages S-页数
  3. E - Pages 电子-页面
  4. L - Pages L-页数
  5. C - Pages C-页面
  6. D - Pages D-页数
  7. Anything else (H, R, etc) 其他(H,R等)

I have come up with a class to write my comparing, however it only slightly works the way I want it to. 我想出了一个类来写我的比较,但它只是稍微的作品,我希望它的方式。 Here is the class, currently it assures that the COVER page is always first, however I don't know where to continue. 这是课程,目前它确保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);
    }
}

My question is how do I conform this class to fit the above criteria for sorting the files. 我的问题是如何使此类符合上述文件排序标准。 The files' format looks somewhat like this, where the ending indicates the page type. 文件的格式看起来像这样,其中结尾表示页面类型。

C:\\Users\\Desktop\\PDFs\\T-0023\\T-0023_H1.pdf 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_c3_S01.pdf

C:\\Users\\Desktop\\PDFs\\T-0023\\T-0023_L01.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_H3A.pdf

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

I'd create a collection of the types you want in order: 我将按顺序创建所需类型的集合:

var types = "SELCD";

int file1Index = types.IndexOf(Char.ToUpper(lastBit1[0]));
int file2Index = types.IndexOf(Char.ToUpper(lastBit2[0]));

if (file1Index == -1 && file2Index != -1)
   return 1;

if (file1Index > file2Index)
    return 1;
if (file1Index < file2Index)
   return -1;

// Else do your alphabetic sort

EDIT Updated code to account for file2's character being in the collection, but not file1's. 编辑更新的代码以说明文件2的字符在集合中,而不是文件1的字符。

Here's another similar way to do it, where you keep a list of the items you want to order by, and then for each file you determine if the "last bit" starts with any of the items in the list by getting the IndexOf for the FirstOrDefault item in the list where the item StartsWith that string. 这是另一种类似的操作方式,其中保留要排序的项目的列表,然后对于每个文件,通过获取IndexOf来确定“最后一位”是否以列表中的任何项目开头FirstOrDefault列表中的项目,其中项目StartsWith该字符串。

The logic goes: 逻辑是:

  • If the indexes of both items are the same, then return the comparison of their 'lastBit' strings, and if those are the same use the whole file name. 如果两项的索引相同,则返回其“ lastBit”字符串的比较,如果相同,则使用整个文件名。

  • If the first item is not contained in the list then return 1 (first item is greater than second) 如果列表中未包含第一项,则返回1 (第一项大于第二项)

  • If the second item is not in the list then return -1 (first item is less than the second) 如果第二项不在列表中,则返回-1 (第一项小于第二项)

  • Finally, return the comparison of their indexes in the list 最后,返回列表中它们索引的比较

Here's the code: 这是代码:

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);
    }
}

To test it, I just created a dummy list of file names based on the ones you provided, and added a few more in an unsorted way: 为了测试它,我只是根据您提供的文件名创建了一个虚拟文件名列表,并以未排序的方式添加了一些文件名:

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...");
}

Output 输出量

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM