法国行政区域CSV数据集转带ParentId的树结构实现方案咨询
解决方案
你当前代码仅提取了各层级的独立唯一值,丢失了不同层级名称之间的绑定关系,按以下步骤修改即可自动完成ParentId赋值,且支持同类场景复用:
- 新增名称映射字典,用于快速查询节点ID,避免重复遍历列表
// 构建【节点名称+层级】到节点对象的映射字典 var areaLookup = newCoverageAreas.ToDictionary(area => new { area.Description, area.Level });
- 基于原始CSV数据构建父子关系映射,逐行读取完整的层级链路,提取唯一的父子配对
// 存储子节点对应的父节点信息 var parentRelations = new Dictionary<(string name, string level), (string parentName, string parentLevel)>(); // 去重避免重复处理相同的层级链路 var uniqueHierarchies = coverageAreas.DistinctBy(row => new { row.Level1, row.Level2, row.Level3, row.Level4 }); foreach (var hierarchy in uniqueHierarchies) { // Level2(Region)的父节点是Level1(法国) if (!string.IsNullOrWhiteSpace(hierarchy.Level2)) { parentRelations.TryAdd((hierarchy.Level2, "2"), (hierarchy.Level1, "1")); } // Level3(Department)的父节点是Level2(Region) if (!string.IsNullOrWhiteSpace(hierarchy.Level3)) { parentRelations.TryAdd((hierarchy.Level3, "3"), (hierarchy.Level2, "2")); } // Level4(城市)的父节点是Level3(Department) if (!string.IsNullOrWhiteSpace(hierarchy.Level4)) { parentRelations.TryAdd((hierarchy.Level4, "4"), (hierarchy.Level3, "3")); } }
- 批量为所有节点赋值ParentId
foreach (var area in newCoverageAreas) { // 根节点(Level1,法国)无父节点,ParentId可按需求设为null或0 if (area.Level == "1") { area.ParentId = null; continue; } // 查找当前节点的父节点信息,拿到ID赋值 if (parentRelations.TryGetValue((area.Description, area.Level), out var parentInfo) && areaLookup.TryGetValue(new { Description = parentInfo.parentName, Level = parentInfo.parentLevel }, out var parentArea)) { area.ParentId = parentArea.Id; } }
注意事项
- 整套逻辑未硬编码任何行政区划名称,只要是同结构的多层级CSV数据都可以直接复用
- 若后续层级数量发生变化,仅需调整父子关系映射的对应规则即可,核心逻辑无需修改
- 可根据业务需求补充空值校验、异常处理逻辑,避免CSV数据缺失导致的报错
内容的提问来源于stack exchange,提问作者Delfino
相关产品推荐
相关产品推荐

