列表重复项检测与优化:正则提取去重及重复项索引获取
一、正则提取阶段直接去重的优化方案
原代码用List.Contains()判断去重,不仅效率低(List的Contains是线性遍历,数据量大时性能差),还只能处理单个文件内的重复,跨文件的重复会在后续调用中依然出现。更高效的方式是使用HashSet<string>,它的Add()方法会自动忽略重复项,且查找/插入操作的时间复杂度为O(1)。
1. 修改提取方法,用HashSet实现去重
public HashSet<string> GetLinks(string message, HashSet<string> existingLinks = null) { // 传入已有的HashSet实现全局去重,否则新建 var linksSet = existingLinks ?? new HashSet<string>(); string txt = message; foreach (Match item in Regex.Matches(txt, @"(http|ftp|https):\/\/([\w\-_]+(?:(?:\.[\w\-_]+)+))([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?")) { if (item.Value.Contains("thumbs")) { int index1 = item.Value.IndexOf("mp4"); string news = ReplaceLastOccurrence(item.Value, "thumbs", "videos"); if (index1 != -1) { string result = news.Substring(0, index1 + 3); // HashSet自动跳过重复项,无需手动判断Contains linksSet.Add(result); } } } return linksSet; }
2. 调用时实现全局去重
// 全局HashSet存储所有唯一链接 var videosLinks = new HashSet<string>(); string[] files = Directory.GetFiles(@"D:\Videos\"); foreach (string file in files) { // 把同一个HashSet传入每个文件的提取方法,实现跨文件去重 GetLinks(File.ReadAllText(file), videosLinks); } // 如需转成List格式 var uniqueLinksList = videosLinks.ToList();
这种方式不管是单个文件内还是跨文件的重复链接,都会在提取阶段直接被过滤,性能远优于原方法。
二、生成重复项及其索引的列表
要获取重复链接的内容和它们在原全量列表中的索引,需先收集所有提取结果(包含重复),再通过分组统计筛选出重复项:
1. 定义存储重复信息的类
public class DuplicateLinkInfo { public string Link { get; set; } public List<int> Indices { get; set; } }
2. 修改提取方法,保留所有结果(不做去重)
public List<string> GetLinksWithDuplicates(string message) { List<string> list = new List<string>(); string txt = message; foreach (Match item in Regex.Matches(txt, @"(http|ftp|https):\/\/([\w\-_]+(?:(?:\.[\w\-_]+)+))([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?")) { if (item.Value.Contains("thumbs")) { int index1 = item.Value.IndexOf("mp4"); string news = ReplaceLastOccurrence(item.Value, "thumbs", "videos"); if (index1 != -1) { string result = news.Substring(0, index1 + 3); list.Add(result); // 保留所有提取结果,包括重复 } } } return list; }
3. 统计重复项及其索引
// 收集所有提取结果(含重复) var allLinks = new List<string>(); string[] files = Directory.GetFiles(@"D:\Videos\"); foreach (string file in files) { allLinks.AddRange(GetLinksWithDuplicates(File.ReadAllText(file))); } // 分组统计,筛选出出现次数>1的链接及其索引 var duplicateLinks = allLinks .Select((link, index) => new { Link = link, Index = index }) .GroupBy(x => x.Link) .Where(group => group.Count() > 1) .Select(group => new DuplicateLinkInfo { Link = group.Key, Indices = group.Select(item => item.Index).ToList() }) .ToList();
最终duplicateLinks列表中,每个元素包含重复的链接内容,以及该链接在allLinks列表中所有出现的索引位置。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

