遍历两个List并更新匹配元素的InternalRef值
public class Car { public int Id { get; set; } public string Name {get; set;} public string? InternalRef {get; set;} } var list1 = new List<Car>(); list1.Add(new Car{ Id = 1, Name = "Audi", InternalRef = "abc"}); list1.Add(new Car{ Id = 2, Name = "Toyota", InternalRef = "dfg"}); list1.Add(new Car{ Id = 3, Name = "Seat" }); var list2 = new List<Car>(); list2.Add(new Car{ Id = 1, Name = "Audi", InternalRef = "abc"}); list2.Add(new Car{ Id = 2, Name = "Toyota", InternalRef = "dfg"}); list2.Add(new Car{ Id = 3, Name = "Seat", InternalRef = "xvc" });
需求
- 找出所有Id相同的元素
- 当list1中元素的InternalRef为null时,将list2中对应匹配元素的InternalRef值赋值给它
现有尝试代码
var combined = (from c in list1 where list2.Any(x => c.Id == x.Id) select c).ToList();
这段代码能得到所有Id相同元素的列表,但我仍需要实现InternalRef的赋值逻辑
解决方案
方式一:遍历处理(直观高效)
先将list2转为以Id为键的字典,提升匹配效率,再遍历list1完成筛选和赋值:
// 转换为字典,避免多次遍历list2 var list2Dict = list2.ToDictionary(car => car.Id); var result = new List<Car>(); foreach (var car1 in list1) { if (list2Dict.TryGetValue(car1.Id, out var car2)) { result.Add(car1); // 当list1元素的InternalRef为空时,赋值list2对应的值 if (car1.InternalRef == null) { car1.InternalRef = car2.InternalRef; } } }
方式二:LINQ结合修改操作
如果偏好LINQ写法,可以在筛选后直接处理赋值:
var list2Dict = list2.ToDictionary(c => c.Id); var combined = list1 .Where(c1 => list2Dict.ContainsKey(c1.Id)) .Select(c1 => { if (c1.InternalRef == null) { c1.InternalRef = list2Dict[c1.Id].InternalRef; } return c1; }) .ToList();
方式三:不修改原列表(创建新实例)
如果不想改动list1中的原始元素,可以创建新的Car对象:
var list2Dict = list2.ToDictionary(c => c.Id); var combined = list1 .Where(c1 => list2Dict.ContainsKey(c1.Id)) .Select(c1 => new Car { Id = c1.Id, Name = c1.Name, InternalRef = c1.InternalRef ?? list2Dict[c1.Id].InternalRef }) .ToList();
说明
- 将list2转为字典后,查找匹配元素的时间复杂度从O(n)降到O(1),数据量较大时性能优势明显
- 前两种方式会直接修改list1中的元素(因为Car是引用类型),第三种方式则生成全新的列表,不影响原数据
内容的提问来源于stack exchange,提问作者user1765862
相关产品推荐
相关产品推荐

