NET 通用方法:把扁平数据转换为树形数据结构【表格】
1.表格文件:节点打横成一行,根节点需要关联附属信息【Remark1 / Remark2】
2.demo
[Theory] [InlineData(@"C:\Working\TestTreeNode.xlsx")] public void Run(string path) { // 节点后端 属性名集合 var nodeNameList = new List<string> { "Node1", "Node2", "Node3" }; // 最末级节点-附属信息 属性名集合 var propertyNameList = new List<string> { "Remark1", "Remark2" }; var modelList = NpoiHelper.ConvertList<TestNodeDto>(path); var dic = new List<string>(); foreach (var itemModel in modelList) { var itemKey = string.Empty; var itemLastNodeFieldName = itemModel.GetLastNodeFieldName(); for (int i = 0; i < nodeNameList.Count; i++) { // 获取 节点后端 属性名 var itemNodeName = nodeNameList[i]; // 获取 节点后端 属性值 var itemNodeValue = itemModel[itemNodeName]; if (itemNodeValue.IsNullOrWhiteSpace()) break; var propertyList = new List<string>(); // 如果是最后一个节点,则获取附属信息 if (itemLastNodeFieldName.Equals(itemNodeName)) { foreach (var itemPropertyName in propertyNameList) { propertyList.Add($"{itemPropertyName}:{itemModel[itemPropertyName]}"); } } itemKey += itemNodeValue; // 过滤重复节点 if (!dic.Contains(itemKey)) { dic.Add(itemKey); var prefix = Enumerable.Repeat("\t", i).Join(""); _testOutputHelper.WriteLine($"{prefix}{itemNodeName}:{itemNodeValue}\t{propertyList.Join("\t")}"); } } } _testOutputHelper.WriteLine("Run"); }
3.TestNodeDto
/// <summary> /// 测试树形节点 实体 /// </summary> public class TestNodeDto { public string Code { get; set; } [DisplayName("Node1")] public string Node1 { get; set; } [DisplayName("Node2")] public string Node2 { get; set; } [DisplayName("Node3")] public string Node3 { get; set; } [DisplayName("Remark1")] public string Remark1 { get; set; } [DisplayName("Remark2")] public string Remark2 { get; set; } /// <summary> /// 获取最后一个节点字段名 /// </summary> /// <returns></returns> public string GetLastNodeFieldName() { // 从最后一个子节点往根节点判断,只要任意节点有值,则为 最后一个节点 if (!Node3.IsNullOrWhiteSpace()) return nameof(Node3); if (!Node2.IsNullOrWhiteSpace()) return nameof(Node2); if (!Node1.IsNullOrWhiteSpace()) return nameof(Node1); return string.Empty; } public string this[string fieldName] { get { switch (fieldName) { case nameof(Node1): return Node1; case nameof(Node2): return Node2; case nameof(Node3): return Node3; case nameof(Remark1): return Remark1; case nameof(Remark2): return Remark2; default: return string.Empty; } } } }
4.输出结果
Node1:Lv0 Node2:Lv0-1 Node3:Lv0-1-1 Remark1:附属信息1:Lv0-1-1 Remark2:附属信息2:Lv0-1-1 Node3:Lv0-1-2 Remark1:附属信息1:Lv0-1-2 Remark2:附属信息2:Lv0-1-2 Node3:Lv0-1-3 Remark1:附属信息1:Lv0-1-3 Remark2:附属信息2:Lv0-1-3 Node3:Lv0-1-4 Remark1:附属信息1:Lv0-1-4 Remark2:附属信息2:Lv0-1-4 Node3:Lv0-1-5 Remark1:附属信息1:Lv0-1-5 Remark2:附属信息2:Lv0-1-5 Node2:Lv0-2 Node3:Lv0-2-1 Remark1:附属信息1:Lv0-2-1 Remark2:附属信息2:Lv0-2-1 Node3:Lv0-2-2 Remark1:附属信息1:Lv0-2-2 Remark2:附属信息2:Lv0-2-2 Node3:Lv0-2-3 Remark1:附属信息1:Lv0-2-3 Remark2:附属信息2:Lv0-2-3 Node2:Lv0-3 Remark1:附属信息1:Lv0-3 Remark2:附属信息2:Lv0-3 Node2:Lv0-5 Remark1:附属信息1:Lv0-5 Remark2:附属信息2:Lv0-5 Node1:Lv1 Node2:Lv1-1 Node3:Lv1-1-1 Remark1:附属信息1:Lv1-1-1 Remark2:附属信息2:Lv1-1-1 Node2:Lv1-2 Remark1:附属信息1:Lv1-2 Remark2:附属信息2:Lv1-2 Node2:Lv1-3 Remark1:附属信息1:Lv1-3 Remark2:附属信息2:Lv1-3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2018-11-02 【git】常用命令