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
复制代码

 

posted @   Robot-Blog  阅读(109)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2018-11-02 【git】常用命令
点击右上角即可分享
微信分享提示