如何从id_name_date_filetype格式的文件数组中筛选同ID/名称的文件
解决思路与代码优化方案
嘿,我来帮你搞定这个问题!你的核心需求是从格式为id_name_date_filetype的文件集合里,提取所有ID重复或者名称重复的文件,对吧?结合你现有的代码,咱们可以分几步来实现:
第一步:给每个文件绑定ID和名称信息
首先,我们需要把每个文件路径和它对应的ID、名称关联起来——毕竟文件名拆分后,fileNameSplit[0]是ID,fileNameSplit[1]就是名称(前提是你的文件名格式严格符合约定)。这里可以用匿名类型来临时存储这些信息,方便后续处理:
// 先把所有文件和对应的ID、名称映射起来,同时过滤格式错误的文件 var fileWithMetadata = filelist.Select(file => { // 先获取不带扩展名的文件名,避免把.tsv后缀算进去 var fileNameWithoutExt = Path.GetFileNameWithoutExtension(file); var parts = fileNameWithoutExt.Split('_'); // 防止文件名格式不符合要求导致索引越界,这里做个判断 if (parts.Length < 4) { Console.WriteLine($"警告:文件 {file} 格式不符合id_name_date_filetype约定,已跳过"); return null; } return new { FullFilePath = file, FirmId = parts[0], FirmName = parts[1] }; }) // 过滤掉格式错误的文件 .Where(item => item != null) .ToList();
第二步:统计ID和名称的出现次数
接下来,我们需要知道哪些ID或者名称是重复的——通过分组统计就能快速得到每个ID、名称对应的文件数量:
// 统计每个ID对应的文件数量 var idOccurrenceCounts = fileWithMetadata .GroupBy(item => item.FirmId) .ToDictionary(group => group.Key, group => group.Count()); // 统计每个名称对应的文件数量 var nameOccurrenceCounts = fileWithMetadata .GroupBy(item => item.FirmName) .ToDictionary(group => group.Key, group => group.Count());
第三步:筛选出符合条件的文件
现在我们可以根据统计结果,筛选出ID出现多次或者名称出现多次的文件,存入目标数组:
// 提取所有ID重复或名称重复的文件路径 var duplicateFiles = fileWithMetadata .Where(item => idOccurrenceCounts[item.FirmId] > 1 || nameOccurrenceCounts[item.FirmName] > 1) .Select(item => item.FullFilePath) .ToArray();
整合到你的现有代码里
把这段逻辑放到你第二个foreach的位置就行,替换掉空的循环体。如果你还需要对这些筛选后的文件做后续处理(比如按类型读取数据),可以在筛选后再加一层遍历:
// 遍历筛选出的重复文件,按类型读取数据(和你之前的逻辑一致) foreach (string file in duplicateFiles) { var fileName = Path.GetFileName(file).ToLower(); switch (fileName) { case "assets.tsv": assets = ReadDataFromCsv<Asset>(file); break; case "financialaccounts.tsv": financialAccounts = ReadDataFromCsv<FinancialAccount>(file); break; case "households.tsv": households = ReadDataFromCsv<Household>(file); break; case "registrations.tsv": registrations = ReadDataFromCsv<Registration>(file); break; case "representatives.tsv": representatives = ReadDataFromCsv<Representative>(file); break; } }
额外提示
- 如果你的文件名格式可能有变动,建议把ID和名称的位置做成可配置的,或者加更严谨的格式校验
- 如果你需要的是同一个ID下的所有文件或者同一个名称下的所有文件(而不仅仅是重复的),可以直接用
GroupBy分组后取对应的组即可,比如fileWithMetadata.GroupBy(item => item.FirmId)就能得到每个ID对应的文件集合
内容的提问来源于stack exchange,提问作者Novica Josifovski
相关产品推荐
相关产品推荐

