diff --git a/FileMerger.cs b/FileMerger.cs index a011fbe..76af48d 100644 --- a/FileMerger.cs +++ b/FileMerger.cs @@ -3,9 +3,68 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace SlideCombine { + /// + /// Bkmk文件智能排序比较器 + /// 按文件夹名称中的数字部分进行排序 + /// + public class BkmkFileComparer : IComparer + { + 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 xFolder = Path.GetFileName(Path.GetDirectoryName(x)); + var yFolder = Path.GetFileName(Path.GetDirectoryName(y)); + + // 提取数字部分进行智能排序 + var xNumber = ExtractNumberFromFolder(xFolder); + var yNumber = ExtractNumberFromFolder(yFolder); + + // 如果都有数字,按数字大小排序 + if (xNumber.HasValue && yNumber.HasValue) + { + int result = xNumber.Value.CompareTo(yNumber.Value); + if (result != 0) return result; + } + // 如果只有一方有数字,有数字的排前面 + else if (xNumber.HasValue) + { + return -1; + } + else if (yNumber.HasValue) + { + return 1; + } + + // 如果都没有数字或数字相同,按完整字符串排序 + return string.Compare(x, y, StringComparison.OrdinalIgnoreCase); + } + + private int? ExtractNumberFromFolder(string folderName) + { + // 使用正则表达式提取文件夹名称中的数字部分 + // 支持格式:CH-875 1-3, CH-875 4-6, CH-875 10-12, Volume 2, Part 1等 + var match = Regex.Match(folderName, @"(?:[\w-]+\s+)?(\d+)", RegexOptions.IgnoreCase); + + if (match.Success && match.Groups.Count > 1) + { + string numberStr = match.Groups[1].Value; + if (int.TryParse(numberStr, out int number)) + { + return number; + } + } + + return null; + } + } public class ProcessResult { public string BaseFileName { get; set; } @@ -62,7 +121,7 @@ namespace SlideCombine // 处理每个分组 foreach (var group in fileGroups) { - var result = ProcessFileGroup(group.Key, group.Value.OrderBy(f => f).ToList(), txtSourcePath); + var result = ProcessFileGroup(group.Key, group.Value.OrderBy(f => f, new BkmkFileComparer()).ToList(), txtSourcePath); results.Add(result); } } diff --git a/智能排序说明.md b/智能排序说明.md new file mode 100644 index 0000000..a3ce5ec --- /dev/null +++ b/智能排序说明.md @@ -0,0 +1,109 @@ +# 智能排序算法改进说明 + +## 🎯 改进前后对比 + +### 改进前(字符串排序) +``` +原始文件列表: +- CH-875 1-3/FreePic2Pdf_bkmk.txt +- CH-875 10-12/FreePic2Pdf_bkmk.txt +- CH-875 2-4/FreePic2Pdf_bkmk.txt +- CH-875 4-6/FreePic2Pdf_bkmk.txt + +字符串排序结果(错误): +1. CH-875 1-3.txt ← 正确 +2. CH-875 10-12.txt ← 错误!应该是第4个 +3. CH-875 2-4.txt ← 错误!应该是第2个 +4. CH-875 4-6.txt ← 错误!应该是第3个 +``` + +### 改进后(智能数字排序) +``` +智能排序结果(正确): +1. CH-875 1-3.txt ← 第1个 +2. CH-875 2-4.txt ← 第2个 +3. CH-875 4-6.txt ← 第3个 +4. CH-875 10-12.txt ← 第4个 +``` + +## 🔧 算法实现 + +### 核心逻辑 +1. **提取文件夹名称**:从完整路径中提取文件夹部分 +2. **正则表达式匹配**:使用正则提取数字部分 +3. **智能比较**:优先按数字大小,无数字则按字符串 + +### 正则表达式 +```csharp +@"(?:[\w-]+\s+)?(\d+)" +``` + +**支持的格式:** +- `CH-875 1-3` → 提取 `1` +- `CH-875 10-12` → 提取 `10` +- `Volume 2` → 提取 `2` +- `Part 1` → 提取 `1` + +### 比较规则 +1. **都有数字**:按数字大小比较 +2. **只有一方有数字**:有数字的排前面 +3. **都无数字**:按完整字符串比较 + +## 📋 测试用例 + +### 测试案例1:标准格式 +``` +输入: +CH-875 1-3, CH-875 4-6, CH-875 7-9, CH-875 10-12 + +输出: +CH-875 1-3 → CH-875 4-6 → CH-875 7-9 → CH-875 10-12 +``` + +### 测试案例2:跨位数 +``` +输入: +CH-875 2-3, CH-875 10-15, CH-875 1-4, CH-875 11-12 + +输出: +CH-875 1-4 → CH-875 2-3 → CH-875 10-15 → CH-875 11-12 +``` + +### 测试案例3:无数字格式 +``` +输入: +CH-875-第一章, CH-875-第二章, CH-875-第三章 + +输出: +CH-875-第一章 → CH-875-第二章 → CH-875-第三章(按字符串排序) +``` + +### 测试案例4:混合格式 +``` +输入: +CH-875 Part 1, CH-875 2-3, CH-875 Chapter 3, CH-875 1-2 + +输出: +CH-875 1-2 → CH-875 2-3 → CH-875 Part 1 → CH-875 Chapter 3 +``` + +## ✨ 优势 + +1. **正确排序**:解决跨位数排序问题 +2. **格式兼容**:支持多种文件命名格式 +3. **向后兼容**:无数字格式仍然正常工作 +4. **性能良好**:一次提取,多次比较 + +## 🔍 代码位置 + +**FileMerger.cs 第65行:** +```csharp +var result = ProcessFileGroup(group.Key, group.Value.OrderBy(f => f, new BkmkFileComparer()).ToList(), txtSourcePath); +``` + +**BkmkFileComparer 类:** +- 位置:FileMerger.cs 第14-67行 +- 功能:智能文件比较器 +- 特点:基于数字提取的排序算法 + +这个改进确保了文件夹按照自然的阅读顺序进行合并! \ No newline at end of file