如何在C#中高效获取列表集合中的公共元素
在C#中高效获取多列表的公共元素
给定包含多个列表的集合,比如:
var result = new List<List<string>> { new List<string> { "a", "b", "c" }, new List<string> { "c", "b", "e", "r" }, new List<string> { "c", "b" } };
我们需要提取所有列表的公共元素,预期结果为{"b", "c"}。
你的代码思路与修正
你当前的思路是对的:先取前两个列表的交集,再依次和后续列表求交集,但存在语法错误和可优化点:
- 缺少必要分号,
foreach循环变量l未声明类型(需加var) result[2..^0]是错误的范围表达式,应改为result[2..]获取索引2开始的剩余元素
修正后的基础版本:
if (result == null || !result.Any()) { return Enumerable.Empty<string>(); // 处理空集合的边界情况 } var common = result[0].Intersect(result[1]).ToList(); foreach (var l in result[2..]) { common = common.Intersect(l).ToList(); if (!common.Any()) break; // 提前终止:无公共元素时无需继续循环 }
更高效的实现方案
要进一步提升效率,优先以最短的列表作为初始交集集合——因为Intersect的时间复杂度和集合大小正相关,用最短列表起步能大幅减少后续比较次数。同时改用HashSet<T>的IntersectWith方法,它直接在原集合上修改,避免多次创建新集合的开销:
if (result == null || !result.Any()) { return Enumerable.Empty<string>(); } // 找到最短列表作为初始交集 var shortestList = result.OrderBy(list => list.Count).First(); var common = new HashSet<string>(shortestList); foreach (var list in result.Where(l => l != shortestList)) { common.IntersectWith(list); if (common.Count == 0) break; // 提前终止,避免无效计算 } // 转换为目标列表类型 var finalResult = common.ToList();
额外注意事项
- 如果需要保留元素的重复次数(比如所有列表都出现n次的元素才保留n次),则不能用
Intersect,需统计每个元素在所有列表中的出现次数,仅保留次数等于列表总数的元素 - 务必处理空集合、单个列表等边界场景,避免索引越界或异常
内容的提问来源于stack exchange,提问作者Nicolas REY
相关产品推荐
相关产品推荐

