使用C# LINQ合并含匹配与不匹配数据的三个列表
C# 合并三列匹配键相同、值列不同的列表
需求说明
现有三个列表,其中ID和Name为共同匹配列,第三列分别为Value1、Value2、Value3(部分条目可能缺失对应值),需要合并为一个包含所有条目(含仅在单个列表中存在的条目)的结果列表,示例如下:
原始列表
- ListA:
| ID | Name | Value1 |
|---|---|---|
| 1 | A | 10 |
| 2 | B | 20 |
| 3 | C | 30 |
- ListB:
| ID | Name | Value2 |
|---|---|---|
| 1 | A | 15 |
| 2 | B | 40 |
| 3 | D | 50 |
| 4 | E | 60 |
- ListC:
| ID | Name | Value3 |
|---|---|---|
| 1 | A | |
| 2 | B | 50 |
| 3 | F | 60 |
期望合并结果
| ID | Name | Value1 | Value2 | Value3 |
|---|---|---|---|---|
| 1 | A | 10 | 15 | |
| 2 | B | 20 | 40 | 50 |
| 3 | C | 30 | ||
| 3 | D | 50 | ||
| 4 | E | 60 | ||
| 3 | F | 60 |
实现步骤与代码
1. 定义实体类
先为三个原始列表和结果列表定义强类型实体:
// ListA的实体 public class ItemA { public int ID { get; set; } public string Name { get; set; } public int? Value1 { get; set; } // 用可空类型处理缺失值 } // ListB的实体 public class ItemB { public int ID { get; set; } public string Name { get; set; } public int? Value2 { get; set; } } // ListC的实体 public class ItemC { public int ID { get; set; } public string Name { get; set; } public int? Value3 { get; set; } } // 合并结果的实体 public class MergedItem { public int ID { get; set; } public string Name { get; set; } public int? Value1 { get; set; } public int? Value2 { get; set; } public int? Value3 { get; set; } }
2. 合并逻辑实现
先收集所有唯一的ID+Name组合,再分别从三个列表中匹配对应值,组装结果:
// 示例原始数据 var listA = new List<ItemA> { new ItemA { ID = 1, Name = "A", Value1 = 10 }, new ItemA { ID = 2, Name = "B", Value1 = 20 }, new ItemA { ID = 3, Name = "C", Value1 = 30 } }; var listB = new List<ItemB> { new ItemB { ID = 1, Name = "A", Value2 = 15 }, new ItemB { ID = 2, Name = "B", Value2 = 40 }, new ItemB { ID = 3, Name = "D", Value2 = 50 }, new ItemB { ID = 4, Name = "E", Value2 = 60 } }; var listC = new List<ItemC> { new ItemC { ID = 1, Name = "A" }, // Value3缺失 new ItemC { ID = 2, Name = "B", Value3 = 50 }, new ItemC { ID = 3, Name = "F", Value3 = 60 } }; // 收集所有唯一的ID+Name键 var allKeys = listA.Select(x => (x.ID, x.Name)) .Union(listB.Select(x => (x.ID, x.Name))) .Union(listC.Select(x => (x.ID, x.Name))) .ToList(); // 组装合并结果 var mergedList = allKeys.Select(key => new MergedItem { ID = key.ID, Name = key.Name, Value1 = listA.FirstOrDefault(x => x.ID == key.ID && x.Name == key.Name)?.Value1, Value2 = listB.FirstOrDefault(x => x.ID == key.ID && x.Name == key.Name)?.Value2, Value3 = listC.FirstOrDefault(x => x.ID == key.ID && x.Name == key.Name)?.Value3 }).ToList();
3. 性能优化(大数据量场景)
如果列表数据量较大,可提前为三个列表创建ID+Name键的字典,替代线性查找提升效率:
// 预创建字典优化查找 var dictA = listA.ToDictionary(x => (x.ID, x.Name)); var dictB = listB.ToDictionary(x => (x.ID, x.Name)); var dictC = listC.ToDictionary(x => (x.ID, x.Name)); var mergedList = allKeys.Select(key => new MergedItem { ID = key.ID, Name = key.Name, Value1 = dictA.TryGetValue(key, out var itemA) ? itemA.Value1 : null, Value2 = dictB.TryGetValue(key, out var itemB) ? itemB.Value2 : null, Value3 = dictC.TryGetValue(key, out var itemC) ? itemC.Value3 : null }).ToList();
内容的提问来源于stack exchange,提问作者Youthful Channel
相关产品推荐
相关产品推荐

