如何按唯一字段合并两个C#列表并高效填充空字段?
百万级List集合高效合并方案
现有两个百万级List<Structure>集合list1和list2,需按以下规则合并为list3:
- 当
Model_id相同时,取list1的Category、Link字段,list2的Place字段 list2独有的条目直接保留
原方案存在的问题:
- 用
for循环+FindIndex的方式,每次查找都是线性遍历list1,时间复杂度为O(n*m),百万级数据下会导致耗时超2小时 - LINQ内连接仅能获取两个集合的交集,丢失了
list2中独有的条目
最优解决方案:基于Dictionary的哈希查找
利用Dictionary将list1的Model_id作为键存储,哈希查找的平均时间复杂度为O(1),整体操作时间复杂度降为O(n + m),能大幅提升处理速度。
代码实现:
// 先将list1转换为以Model_id为键的Dictionary,O(n)时间 var list1Dict = list1.ToDictionary(s => s.Model_id); // 预先设置list3容量,避免动态扩容的性能损耗 List<Structure> list3 = new List<Structure>(list2.Count); foreach (var item2 in list2) { if (list1Dict.TryGetValue(item2.Model_id, out var item1)) { // 存在相同Model_id,合并字段 list3.Add(new Structure { Model_id = item2.Model_id, Category = item1.Category, Place = item2.Place, Link = item1.Link }); } else { // list2独有的条目,直接添加 list3.Add(item2); } }
补充:LINQ左外连接实现
如果偏好LINQ语法,可以使用左外连接(join into + DefaultIfEmpty)保留list2的所有条目,同时匹配list1的数据:
var list3 = (from item2 in list2 join item1 in list1 on item2.Model_id equals item1.Model_id into joinedGroup from matchedItem1 in joinedGroup.DefaultIfEmpty() select new Structure { Model_id = item2.Model_id, Category = matchedItem1?.Category, Place = item2.Place, Link = matchedItem1?.Link }).ToList();
注:该方式性能略逊于Dictionary方案,但远优于原始for循环,适合习惯LINQ语法的场景。
性能优化要点
- 初始化
list3时预先指定容量,避免List动态扩容带来的内存分配和复制开销 - 使用
TryGetValue替代ContainsKey+索引取值,减少一次哈希查找操作,提升效率 ToDictionary内部仅遍历list1一次,哈希表构建效率极高
内容的提问来源于stack exchange,提问作者K-Z
相关产品推荐
相关产品推荐

