將有父子關係的一維數組轉換成樹形結構(多維)數據

前端轉換:

已知數據源:

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前端

 

後端轉換:

在平時的開發工做中,常常遇到這樣一個場景,在數據庫中存儲了具備父子關係的數據,須要將這些數據以樹形結構的形式在界面上進行展現。本文的目的是提供了一個通用的編程模型,解決將具備父子關係的數據轉換成樹形結構的問題。若有不正之處,歡迎你們批評指正。java

編程模型


咱們以北京行政區劃爲例,講解整個模型。node

北京市:市轄區 縣數據庫

市轄區:東城區 西城區 朝陽區 豐臺區 石景山區 海淀區 門頭溝區 房山區 通州區 順義區 昌平區 大興區 懷柔區 平谷區編程

縣:密雲縣 延慶縣json

TreeNode:定義樹的節點對象segmentfault

  • nodeId:樹節點Id。
  • nodeName:樹節點名稱。
  • parentNodeId:樹節點父Id。
  • orderNum:節點在樹中的排序號,在同一節點下進行排序。
  • level:當前樹節點所在的層級,根節點爲第一層。
  • parent:當前樹節點的父節點。
  • children:當前樹節點的兒子節點。
  • allChildren:當前樹節點的子孫節點。


ITree:定義樹對象要實現的方法。後端

  • getTree():以 List 形式返回樹的全部的 TreeNode 對象。
  • getRoot():以 List 形式返回樹的根節點,多是一個或者多個。
  • getTreeNode(String nodeId):根據 nodeId 返回對應的 TreeNode 對象。


Tree:實現 ITree 接口,提供樹的完整功能。maven

  • getTree():以 List 形式返回樹的全部的 TreeNode 對象。
  • getRoot():以 List 形式返回樹的根節點,多是一個或者多個。
  • getTreeNode(String nodeId):根據 nodeId 返回對應的 TreeNode 對象。


ITreeNode:定義模板方法,構造樹形結構的類要實現該接口,Tree 經過調用該接口中的方法獲取 nodeId nodeName parentNodeId orderNum 數據。ide

  • 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>
相關文章
相關標籤/搜索