如何用LINQ筛选两个有序文件路径列表中的匹配序列号项
用LINQ高效处理匹配序列号的文件路径列表
核心思路
先从每个文件路径中提取6位序列号,再依次完成以下操作:
- 移除单个列表内重复序列号的项(保留首次出现的条目,维持原列表顺序)
- 找出两个列表共有的序列号集合
- 基于共有序列号筛选两个列表,最终得到一一匹配、无重复且有序的结果
具体实现代码
首先写一个提取序列号的辅助方法,用正则精准匹配文件名里的6位数字:
using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; public static string ExtractSerialNumber(string filePath) { // 匹配文件名中"actual_fileName_"后的6位数字 var match = Regex.Match(filePath, @"actual_fileName_(\d{6})\.\w+$"); return match.Success ? match.Groups[1].Value : null; }
然后用LINQ完成整个处理流程:
// 处理第一个列表:过滤无效序列号、去重(保留首次出现的条目),关联序列号与路径 var firstWithSerial = firstList .Select(path => new { Path = path, Serial = ExtractSerialNumber(path) }) .Where(item => !string.IsNullOrEmpty(item.Serial)) .GroupBy(item => item.Serial) .Select(group => group.First()) .ToList(); // 处理第二个列表,逻辑与第一个完全一致 var secondWithSerial = secondList .Select(path => new { Path = path, Serial = ExtractSerialNumber(path) }) .Where(item => !string.IsNullOrEmpty(item.Serial)) .GroupBy(item => item.Serial) .Select(group => group.First()) .ToList(); // 高效找出两个列表共有的序列号 var commonSerials = new HashSet<string>(firstWithSerial.Select(item => item.Serial)) .Intersect(secondWithSerial.Select(item => item.Serial)); // 筛选出对应共有序列号的条目,保持原列表顺序 var filteredFirstList = firstWithSerial .Where(item => commonSerials.Contains(item.Serial)) .Select(item => item.Path) .ToList(); var filteredSecondList = secondWithSerial .Where(item => commonSerials.Contains(item.Serial)) .Select(item => item.Path) .ToList();
代码细节说明
- 序列号提取:正则表达式精准锁定文件名中目标位置的6位数字,避免误匹配路径里的其他数字
- 列表去重:通过
GroupBy按序列号分组,取每组第一个元素,既完成去重又保留了原列表的顺序 - 共有序列号查找:用
HashSet的Intersect方法实现高效交集计算,性能远优于普通遍历比对 - 结果筛选:基于共有序列号过滤后,最终的两个列表会完全匹配序列号,且无重复、顺序与原列表一致
如果你的文件名前缀不是固定的actual_fileName_,可以调整正则表达式的前缀部分,比如改成@"_(\d{6})\.\w+$",匹配任意下划线后的6位数字(前提是文件名里只有这一处6位数字序列号)。
内容的提问来源于stack exchange,提问作者Jan Badillo
相关产品推荐
相关产品推荐

