问题描述
source:
/a/b/c/d/e
/a/b/e/f/g
/a/b/h
/a/i/j
/a/i/k
what I need:
a
/ \
b i
/|\ / \
c e h j k
| |
d f
| |
e g
程序源代码
JavaScript
let treeDTO = [];
let array = [
'a/b/c/d/e',
'a/b/e/f/g',
'a/b/h',
'a/i/j',
'a/i/k'
];
array.map((item) => {
let key = item; // key is the full path
let nodeArray = key.split('/'); // split the full path with '/'
// 递归
let children = treeDTO;
// 构建根节点
if (children.length == 0) {
let root = {
key: nodeArray[0]
};
if (nodeArray.length > 1) {
root.children = [];
}
children.push(root);
} else {
// 循环构建子节点
for (let i in nodeArray) {
console.log("i:" + i);
console.log("nodeArray:" + nodeArray);
let node = {
key: nodeArray[i]
};
if (i != nodeArray.length) {
node.children = [];
}
if (children.length == 0) {
children.push(node);
}
let isExist = false;
for (let j in children) {
console.log("j:" + j);
if (children[j].key == node.key) {
if (i != nodeArray.length - 1 && !children[j].children) {
children[j].children = [];
}
children = (i == nodeArray.length - 1 ? children : children[j].children);
console.log("children:" + JSON.stringify(children));
isExist = true;
break;
}
}
if (!isExist) {
children.push(node);
if (i != nodeArray.length - 1 && !children[children.length - 1].children) {
children[children.length - 1].children = [];
}
children = (i == nodeArray.length - 1 ? children : children[children.length - 1].children);
}
}
}
});
console.log(treeDTO);
/* source:
/a/b/c/d/e
/a/b/e/f/g
/a/b/h
/a/i/j
/a/i/k
what I need:
a
/ \
b i
/|\ / \
c e h j k
| |
d f
| |
e g
*/
Java
节点是通用泛型数据模型:
import com.alibaba.fastjson.JSON;
import java.util.Arrays;
/**
* @author: Jack
* 2020-01-11 00:17
*/
public class Main {
public static void main(String[] args) {
Tree<String> forest = new Tree<String>("root");
Tree<String> current = forest;
for (String tree :
Arrays.asList(
"a/b/c/d/e",
"a/b/e/f/g",
"a/b/h",
"a/i/j",
"a/i/k")) {
Tree<String> root = current;
for (String data : tree.split("/")) {
current = current.child(data);
}
current = root;
}
forest.accept(new TreeVisitor());
System.out.println(JSON.toJSONString(forest));
}
}
import java.util.LinkedHashSet;
import java.util.Set;
/**
* @author: Jack
* 2020-01-11 00:13
*/
class Tree<T> implements Visitable<T> {
// NB: LinkedHashSet preserves insertion order
private Set<Tree> children = new LinkedHashSet<Tree>();
private T data;
Tree(T data) {
this.data = data;
}
public void accept(Visitor<T> visitor) {
visitor.visitData(this, data);
for (Tree child : children) {
Visitor<T> childVisitor = visitor.visitTree(child);
child.accept(childVisitor);
}
}
Tree child(T data) {
for (Tree child : children) {
if (child.data.equals(data)) {
return child;
}
}
return child(new Tree(data));
}
Tree child(Tree<T> child) {
children.add(child);
return child;
}
public Set<Tree> getChildren() {
return children;
}
public void setChildren(Set<Tree> children) {
this.children = children;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
/**
* @author: Jack
* 2020-01-11 00:13
*/
interface Visitor<T> {
Visitor<T> visitTree(Tree<T> tree);
void visitData(Tree<T> parent, T data);
}
/**
* @author: Jack
* 2020-01-11 00:13
*/
interface Visitable<T> {
void accept(Visitor<T> visitor);
}
/**
* @author: Jack
* 2020-01-11 00:15
*/
class TreeVisitor implements Visitor<String> {
TreeVisitor() {
}
public Visitor<String> visitTree(Tree<String> tree) {
return new TreeVisitor();
}
public void visitData(Tree<String> parent, String data) {
}
}
Kotlin
自定义具体化的节点模型:
import java.util.*
/**
* @author: Jack
* 2020-01-11 02:35
*/
class NavTree : NavVisitable {
var deptNo = ""
var deptName = ""
var hasPermission = false
var leaf = false
var children: MutableSet<NavTree> = LinkedHashSet()
constructor(deptNo: String, deptName: String, hasPermission: Boolean, leaf: Boolean) {
this.deptNo = deptNo
this.deptName = deptName
this.hasPermission = hasPermission
this.leaf = leaf
}
/**
* 递归遍历
*/
override fun visit(visitor: NavVisitor) {
visitor.visitTree(this)
for (child in children) {
val childVisitor = visitor.visitTree(child)
child.visit(childVisitor)
}
}
fun children(data: NavTree): NavTree {
for (child in children) {
if (child.deptNo == data.deptNo) {
return child
}
}
children.add(data)
return data
}
}
/**
* @author: Jack
* 2020-01-11 00:15
*/
class NavTreeVisitor : NavVisitor {
override fun visitTree(tree: NavTree): NavVisitor {
return NavTreeVisitor()
}
}
/**
* @author: Jack
* 2020-01-11 00:13
*/
interface NavVisitable {
fun visit(visitor: NavVisitor)
}
/**
* @author: Jack
* 2020-01-11 00:13
*/
interface NavVisitor {
fun visitTree(tree: NavTree): NavVisitor
}
/**
* 构建导航树
* source:
/a/b/c/d/e
/a/b/e/f/g
/a/b/h
/a/i/j
/a/i/k
transform to:
a
/ \
b i
/|\ / \
c e h j k
| |
d f
| |
e g
*/
private fun buildAlibrainNavTree(authorizedDepts: List<DataPermissionDeptDTO>, hasPermissionDeptMap: MutableMap<String, DataPermissionDeptDTO>, deptInfoMap: MutableMap<String, String>): NavTree {
// 顶级根节点
var rootNode = NavTree(
deptNo = "00001",
deptName = "XXX",
leaf = false,
hasPermission = false
)
var current = rootNode
authorizedDepts.map {
val root = current
val length = it.deptNoArray.size
it.deptNoArray.forEachIndexed { index, e ->
val data = NavTree(
deptNo = e,
deptName = deptInfoMap[e] ?: "",
leaf = (index == length - 1),
hasPermission = (hasPermissionDeptMap[e] != null)
)
current = current.children(data)
}
current = root
}
rootNode.visit(NavTreeVisitor())
return rootNode
}
Kotlin 开发者社区
国内第一Kotlin 开发者社区公众号,主要分享、交流 Kotlin 编程语言、Spring Boot、Android、React.js/Node.js、函数式编程、编程思想等相关主题。
越是喧嚣的世界,越需要宁静的思考。