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
ITree:定義樹對象要實現的方法。後端
Tree:實現 ITree 接口,提供樹的完整功能。maven
ITreeNode:定義模板方法,構造樹形結構的類要實現該接口,Tree 經過調用該接口中的方法獲取 nodeId nodeName parentNodeId orderNum 數據。ide
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>