• 将有父子关系的一维数组转换成树形结构(多维)数据


    前端转换:

    已知数据源:

    var data=[
      { id: 40, parentId: 31, note: "的萨达是" }, 
    
      { id: 20, parentId: 11, note: "的萨达是" },
      { id: 22, parentId: 20, note: "dsadas" },
      { id: 12, parentId: null, note: "dsadasad萨达s" }, 
      { id: 11, parentId: undefined, note: "dqwds" }, 
      { id: 24, parentId: 22, note: "搜索" },
      { id: 34, parentId: 22, note: "搜索" }
    ]

    实现代码: 

    function fnSetTreeData(data) {
      var data = [...data];
      var tree = data.filter((father) => {
        var branchArr = data.filter((child) => {
          if (father.id == child.parentId) child._hasParent = true;
          return father.id == child.parentId;
    
          // MARK 为什么这样写就报错 ? 
          // if (father.id == child.parentId) child._hasParent = true;
          // return child._hasParent
        });
        if (branchArr.length > 0) father.children = branchArr;
        return !father._hasParent;
      });
    
      // MARK 为什么在这里还得加一个过滤
      tree = tree.filter((item) => {
        return !item._hasParent;
      })
      return tree
    }
    
    console.log(JSON.stringify(fnSetTreeData(data), null, 2));

    原文出处:

    https://segmentfault.com/q/1010000017234194/a-1020000017236512

    后端转换:

    在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示。本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结构的问题。如有不正之处,欢迎大家批评指正。

    编程模型


    我们以北京行政区划为例,讲解整个模型。

    北京市:市辖区 县

    市辖区:东城区 西城区 朝阳区 丰台区 石景山区 海淀区 门头沟区 房山区 通州区 顺义区 昌平区 大兴区 怀柔区 平谷区

    县:密云县 延庆县

    TreeNode:定义树的节点对象

    • nodeId:树节点Id。
    • nodeName:树节点名称。
    • parentNodeId:树节点父Id。
    • orderNum:节点在树中的排序号,在同一节点下进行排序。
    • level:当前树节点所在的层级,根节点为第一层。
    • parent:当前树节点的父节点。
    • children:当前树节点的儿子节点。
    • allChildren:当前树节点的子孙节点。


    ITree:定义树对象要实现的方法。

    • getTree():以 List 形式返回树的所有的 TreeNode 对象。
    • getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
    • getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。


    Tree:实现 ITree 接口,提供树的完整功能。

    • getTree():以 List 形式返回树的所有的 TreeNode 对象。
    • getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
    • getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。


    ITreeNode:定义模板方法,构造树形结构的类要实现该接口,Tree 通过调用该接口中的方法获取 nodeId nodeName parentNodeId orderNum 数据。

    • getNodeId():获取树节点Id。
    • getNodeName():获取树节点名称。
    • getParentNodeId():获取树节点父Id。
    • getOrderNum():获取节点在树中的排序号,在同一节点下进行排序。

    Org:定义行政区划类,实现 ItreeNode 接口。

    实现代码

    TreeNode类:

    package com.ips.tree;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import com.alibaba.fastjson.annotation.JSONField;
    
    /**
     * <p>Title: 树节点</p>
     * <p>Description:一棵树由许多包含父子关系的节点组成 </p>
     * @author  liuzhibo
     * @date    2017年1月18日
     */
    public class TreeNode {
        //树节点ID
        @JSONField(ordinal=1)
        private String nodeId;
        //树节点名称
        @JSONField(ordinal=2)
        private String nodeName;
        //父节点ID
        @JSONField(ordinal=3)
        private String parentNodeId;
        //节点在树中的排序号
        @JSONField(ordinal=4)
        private int orderNum;
        //节点所在的层级
        @JSONField(ordinal=5)
        private int level;
        private TreeNode parent;
        //当前节点的二子节点
        @JSONField(ordinal=6)
        private List<TreeNode> children = new ArrayList<TreeNode>();
        //当前节点的子孙节点
        private List<TreeNode> allChildren = new ArrayList<TreeNode>();
    
        public TreeNode(ITreeNode obj){
            this.nodeId = obj.getNodeId();
            this.nodeName = obj.getNodeName();
            this.parentNodeId = obj.getNodeParentId();
            this.orderNum = obj.getOrderNum();
        }
        public void addChild(TreeNode treeNode){
            this.children.add(treeNode);
        }
        public void removeChild(TreeNode treeNode){
            this.children.remove(treeNode);
        }
        public String getNodeId() {
            return nodeId;
        }
        public void setNodeId(String nodeId) {
            this.nodeId = nodeId;
        }
        public String getNodeName() {
            return nodeName;
        }
        public void setNodeName(String nodeName) {
            this.nodeName = nodeName;
        }
        public String getParentNodeId() {
            return parentNodeId;
        }
        public void setParentNodeId(String parentNodeId) {
            this.parentNodeId = parentNodeId;
        }
        public int getLevel() {
            return level;
        }
        public void setLevel(int level) {
            this.level = level;
        }
        public TreeNode getParent() {
            return parent;
        }
        public void setParent(TreeNode parent) {
            this.parent = parent;
        }
        public List<TreeNode> getChildren() {
            return children;
        }
        public void setChildren(List<TreeNode> children) {
            this.children = children;
        }
        public int getOrderNum() {
            return orderNum;
        }
        public void setOrderNum(int orderNum) {
            this.orderNum = orderNum;
        }
    
        public List<TreeNode> getAllChildren() {
            if(this.allChildren.isEmpty()){
                for(TreeNode treeNode : this.children){
                    this.allChildren.add(treeNode);
                    this.allChildren.addAll(treeNode.getAllChildren());
                }
            }
            return this.allChildren;
        }   
    }

    ITree接口:

    package com.ips.tree;
    
    import java.util.List;
    
    public interface ITree {
        public List<TreeNode> getTree();
        public List<TreeNode> getRoot();
        public TreeNode getTreeNode(String nodeId);
    }

    Tree类:

    package com.ips.tree;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    
    public class Tree implements ITree {
        private HashMap<String, TreeNode> treeNodesMap = new HashMap<String, TreeNode>();
        private List<TreeNode> treeNodesList = new ArrayList<TreeNode>();
    
        public Tree(List<ITreeNode> list){
            initTreeNodeMap(list);
            initTreeNodeList();
        }
    
        private void initTreeNodeMap(List<ITreeNode> list){
            TreeNode treeNode = null;
            for(ITreeNode item : list){
                treeNode = new TreeNode(item);
                treeNodesMap.put(treeNode.getNodeId(), treeNode);
            }
    
            Iterator<TreeNode> iter = treeNodesMap.values().iterator();
            TreeNode parentTreeNode = null;
            while(iter.hasNext()){
                treeNode = iter.next();
                if(treeNode.getParentNodeId() == null || treeNode.getParentNodeId() == ""){
                    continue;
                }
    
                parentTreeNode = treeNodesMap.get(treeNode.getParentNodeId());
                if(parentTreeNode != null){
                    treeNode.setParent(parentTreeNode);
                    parentTreeNode.addChild(treeNode);
                }
            }
        }
    
        private void initTreeNodeList(){
            if(treeNodesList.size() > 0){
                return;
            }
            if(treeNodesMap.size() == 0){
                return;
            }
            Iterator<TreeNode> iter = treeNodesMap.values().iterator();
            TreeNode treeNode = null;
            while(iter.hasNext()){
                treeNode = iter.next();
                if(treeNode.getParent() == null){
                    this.treeNodesList.add(treeNode);
                    this.treeNodesList.addAll(treeNode.getAllChildren());
                }
            }
        }
    
        @Override
        public List<TreeNode> getTree() {
            return this.treeNodesList;
        }
    
        @Override
        public List<TreeNode> getRoot() {
            List<TreeNode> rootList = new ArrayList<TreeNode>();
            if (this.treeNodesList.size() > 0) {
                for (TreeNode node : treeNodesList) {
                    if (node.getParent() == null)
                        rootList.add(node);
                }
            }
            return rootList;
        }
    
        @Override
        public TreeNode getTreeNode(String nodeId) {
            return this.treeNodesMap.get(nodeId);
        }
    
    }

    ITreeNode 接口:

    package com.ips.tree;
    
    public interface ITreeNode {
        public String getNodeId();
        public String getNodeName();
        public String getNodeParentId();
        public Integer getOrderNum();
    }

    Org 类:

    package com.ips.tree;
    
    public class Org implements ITreeNode {
        private String uuid;
        private String parentId;
        private String name;
        private Integer orderNum;
        private String code;
        private String type;
    
        public Org(){
    
        }
        public Org(String uuid, String parentId, String name, Integer orderNum, String code, String type){
            this.uuid = uuid;
            this.parentId = parentId;
            this.name = name;
            this.orderNum = orderNum;
            this.code = code;
            this.type = type;
        }
        @Override
        public String getNodeId() {
            return this.uuid;
        }
    
        @Override
        public String getNodeName() {
            return this.name;
        }
    
        @Override
        public String getNodeParentId() {
            return this.parentId;
        }
    
        @Override
        public Integer getOrderNum() {
            return this.orderNum;
        }
    
        public String getUuid() {
            return uuid;
        }
    
        public void setUuid(String uuid) {
            this.uuid = uuid;
        }
    
        public String getParentId() {
            return parentId;
        }
    
        public void setParentId(String parentId) {
            this.parentId = parentId;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
        public void setOrderNum(Integer orderNum) {
            this.orderNum = orderNum;
        }
    
    }

    TreeDemo 类:执行该类的 main 方法,查看效果。

    package com.ips.tree;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import com.alibaba.fastjson.JSONObject;
    import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
    
    public class TreeDemo {
    
        public static void main(String[] args) {
            Tree tree = new Tree(genOrgList());
            TreeNode treeNode = tree.getTreeNode("2");
    
            SimplePropertyPreFilter filter = new SimplePropertyPreFilter(); // 构造方法里,也可以直接传需要序列化的属性名字
            filter.getExcludes().add("parent");
            filter.getExcludes().add("allChildren");
            String data = JSONObject.toJSONString(treeNode, filter);
            System.out.println(data);
        }
    
        public static List<ITreeNode> genOrgList(){
            List<ITreeNode> list = new ArrayList<ITreeNode>();
    
            Org org = new Org("2", "1", "北京市", 2, "110000", "2");
            list.add(org);
            org = new Org("3", "2", "市辖区", 3, "110100", "3");
            list.add(org);
            org = new Org("4", "3", "东城区", 4, "110101", "4");
            list.add(org);
            org = new Org("5", "3", "东城区", 5, "110102", "4");
            list.add(org);
            org = new Org("6", "3", "东城区", 6, "110105", "4");
            list.add(org);
            org = new Org("7", "3", "东城区", 7, "110106", "4");
            list.add(org);
            org = new Org("8", "3", "东城区", 8, "110107", "4");
            list.add(org);
            org = new Org("9", "3", "东城区", 9, "110108", "4");
            list.add(org);
            org = new Org("10", "3", "东城区", 10, "110109", "4");
            list.add(org);
            org = new Org("11", "3", "东城区", 11, "110111", "4");
            list.add(org);
            org = new Org("12", "3", "东城区", 12, "110112", "4");
            list.add(org);
            org = new Org("13", "3", "东城区", 13, "110113", "4");
            list.add(org);
            org = new Org("14", "3", "东城区", 14, "110114", "4");
            list.add(org);
            org = new Org("15", "3", "东城区", 15, "110115", "4");
            list.add(org);
            org = new Org("16", "3", "东城区", 16, "110116", "4");
            list.add(org);
            org = new Org("17", "3", "东城区", 17, "110117", "4");
            list.add(org);
            org = new Org("18", "2", "县", 3, "110200", "3");
            list.add(org);
            org = new Org("19", "18", "密云县", 19, "110228", "4");
            list.add(org);
            org = new Org("20", "18", "延庆县", 20, "110229", "4");
            list.add(org);
            return list;
        }
    
    }

    执行结果如下:

    {
        "nodeId": "2",
        "nodeName": "北京市",
        "parentNodeId": "1",
        "orderNum": 2,
        "level": 0,
        "children": [{
            "nodeId": "18",
            "nodeName": "县",
            "parentNodeId": "2",
            "orderNum": 3,
            "level": 0,
            "children": [{
                "nodeId": "19",
                "nodeName": "密云县",
                "parentNodeId": "18",
                "orderNum": 19,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "20",
                "nodeName": "延庆县",
                "parentNodeId": "18",
                "orderNum": 20,
                "level": 0,
                "children": []
            }]
        },
        {
            "nodeId": "3",
            "nodeName": "市辖区",
            "parentNodeId": "2",
            "orderNum": 3,
            "level": 0,
            "children": [{
                "nodeId": "17",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 17,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "15",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 15,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "16",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 16,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "13",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 13,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "14",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 14,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "11",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 11,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "12",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 12,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "10",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 10,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "7",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 7,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "6",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 6,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "5",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 5,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "4",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 4,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "9",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 9,
                "level": 0,
                "children": []
            },
            {
                "nodeId": "8",
                "nodeName": "东城区",
                "parentNodeId": "3",
                "orderNum": 8,
                "level": 0,
                "children": []
            }]
        }]
    }

    注:该示例中使用了 alibaba 的 fastjson 实现类对象序列化,maven 依赖如下:

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.20</version>
    </dependency>

    ---------------------
    作者:zhiboer
    来源:CSDN
    原文:https://blog.csdn.net/claram/article/details/54616485
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    N皇后
    逆波兰中缀转后缀代码
    ImportError: No module named Image
    稳定排序 和 不稳定排序 ::::::::::: 内排序和外排序
    逆波兰中 中缀表达式转后缀表达式的方法
    第一章:Unix基础知识
    软件设计流程
    linux 下 tar.xz 文件的解压方法
    fedora 解决 Python.h:没有那个文件或目录 错误的方法
    Shell排序
  • 原文地址:https://www.cnblogs.com/ryelqy/p/10745548.html
Copyright © 2020-2023  润新知