Convert list to tree, managing a tree and its nodes.
Fork from: https://github.com/DenQ/iron-tree https://github.com/DenQ/list-to-tree
The author of this project is DenQ. This project has only been improved a little.
There is a known bug that may be reported incorrectly when the list order is incorrect. The temporary alternative is as follows:
// 获取描述对象的值
export const getObjectValue = (obj, des) => {
return eval('obj.' + des) // eslint-disable-line
}
/**
* 将json按一定规律组合成父子模式
* @param {[type]} data json数据
* @param {Number} [minPid=0] 最大的父ID(可能不是0,最大的是几就填几,就从几开始排)
* @param {String} [IDString='ID'] ID的别名
* @param {String} [pidString='pid'] 父ID的别名
* @param {String} [childrenString='children'] 生成的子的别名(子的数据就在这个名称下)
* @return {[type]} 父子JSON
*/
export const toTreeData = (
data,
minPid = 0,
IDString = 'ID',
pidString = 'pid',
childrenString = 'children',
sort = 'sort'
) => {
let pos = {}
let tree = []
let n = 0
if (minPid === 'null') {
minPid = null
}
while (data.length !== 0) {
if (getObjectValue(data[n], pidString) == minPid) { // eslint-disable-line
// delete getObjectValue(data[n], pidString)
data[n][childrenString] = []
tree.push(data[n])
pos[getObjectValue(data[n], IDString)] = [tree.length - 1]
data.splice(n, 1)
n--
} else {
let posArray = pos[getObjectValue(data[n], pidString)]
if (posArray !== undefined) {
let obj = tree[posArray[0]]
for (let j = 1; j < posArray.length; j++) {
obj = obj[childrenString][posArray[j]]
}
// delete getObjectValue(data[n], pidString)
data[n][childrenString] = []
obj[childrenString].push(data[n])
pos[getObjectValue(data[n], IDString)] = posArray.concat([
obj[childrenString].length - 1
])
data.splice(n, 1)
n--
}
}
n++
if (n > data.length - 1) {
n = 0
}
}
// sort
const toSort = (tree) => {
tree.sort((a, b) => {
return a[sort] - b[sort]
})
}
const ergodicTree = (tree) => {
for (const n in tree) {
if (tree[n][childrenString] && tree[n][childrenString].length) {
toSort(tree[n][childrenString])
ergodicTree(tree[n][childrenString])
}
}
}
toSort(tree)
ergodicTree(tree)
return tree
}
You can use it
console.time('tree算法')
const girdData = toTreeData(tmp, 'null', 'dataUuid', 'parentUuid', '_children')
console.timeEnd('tree算法')
- Convert list to tree.
- Convert tree to list.
- Tree sort by
last
. - UUID is support.
$ npm install js-tree-list
// JsTreeList.ListToTree Config
const defaultOptions = {
key_id: 'id',
key_parent: 'parent',
key_child: 'child',
key_last: null,
uuid: false,
empty_children: false
}
import JsTreeList from "js-tree-list"
var list = [
{
id: 1,
parent: 0
},
{
id: 2,
parent: 1
},
{
id: 3,
parent: 1
},
{
id: 4,
parent: 2
},
{
id: 5,
parent: 2
},
{
id: 6,
parent: 0
},
{
id: 7,
parent: 0
},
{
id: 8,
parent: 7
},
{
id: 9,
parent: 8
},
{
id: 10,
parent: 0
}
]
const tree = new JsTreeList.ListToTree(list, {
key_id: "id",
key_parent: "parent",
key_child: "children",
key_last: "last"
}).GetTree()
const list = new JsTreeList.TreeToList(tree, {
key_child: "children",
empty_children: true
}).GetList()
console.log(tree)
console.log(list)
[{
"id": 1,
"parent": 0,
"child": [
{
"id": 2,
"parent": 1,
"child": [
{
"id": 4,
"parent": 2
}, {
"id": 5,
"parent": 2
}
]
},
{
"id": 3,
"parent": 1
}
]
}, {
"id": 6,
"parent": 0
}, {
"id": 7,
"parent": 0,
"child": [
{
"id": 8,
"parent": 7,
"child": [
{
"id": 9,
"parent": 8
}
]
}
]
}, {
"id": 10,
"parent": 0
}];
- constructor(list, options)
- params:
list
- array list with elements. Like{ id: 5: parent: 1 }
.options
- optional parameter. Object for describe flags and field names for tree.
- params:
- .GetTree() This method will be return json tree
- example:
tree.GetTree()
- example:
- .sort(callback) The custom sort method
- callback(a, b) - a and b have
Node
type and have methods: add, remove, get, set, sort, traversal, etc... - example:
function compareById(vector) { return (a, b) => { const aid = Number(a.get("id")) const bid = Number(b.get("id")) if (aid > bid) { return vector ? 1 : -1 } else if (aid < bid) { return vector ? -1 : 1 } else { return 0 } } } ltt.sort(compareById(false))
- callback(a, b) - a and b have
// create tree
import JsTreeList from "js-tree-list"
const object = { id: 1, title: "Root" }
const tree = new JsTreeList.Tree(object)
// add nodes
const regularObject = { id: 2, title: "Node 2" }
tree.add(parentNode => {
return parentNode.get("id") === 1
}, regularObject)
// contains node
const targetNode = tree.contains(currentNode => {
return currentNode.get("id") === 2
})
// remove node
const result = tree.remove(currentNode => {
return currentNode.get("id") === 2
})
// traversal
const criteria = currentNode => currentNode.get("id") === 1
tree.traversal(criteria, currentNode => {
currentNode.set("some", true)
})
function compareById(vector) {
return (a, b) => {
const aid = Number(a.get("id"))
const bid = Number(b.get("id"))
if (aid > bid) {
return vector ? 1 : -1
} else if (aid < bid) {
return vector ? -1 : 1
} else {
return 0
}
}
}
tree.sort(compareById(false)) // desc
The following are the other methods available.
This is the class of tree management
- rootNode Root tree node
- type
Node
- type
-
contstructor(object)
- params
- object - json
object
. Optional
- object - json
- return
Three
- example
const object = { id: 1, title: "Root" } const tree = new JsTreeList.Tree(object)
- params
-
.add(criteria, object) Adds a node to the tree if the criterion is true
- params
- criteria(Node) -
function
orstring
. Ifstring
then criteria is "root" - object - content for the node
- criteria(Node) -
- return
Three
- examples
const object = { id: 1, title: "Root" } const tree = new JsTreeList.Tree() const resultTree = tree.add("root", object)
const regularObject = { id: 2, title: "Node 2" } const resultTree = tree.add(parentNode => { return parentNode.get("id") === 1 }, regularObject)
- params
-
.remove(criteria) Removes a node from a tree if the criterion is true
- params
- criteria(Node) - return
boolean
- criteria(Node) - return
- return
boolean
- examples
const result = tree.remove(currentNode => { return currentNode.get("id") === 7 })
- params
-
.contains(criteria) Searches for a node in a tree according to the criterion
- params
- criteria(Node) - return
boolean
- criteria(Node) - return
- return
Node
- examples
const targetNode = tree.contains(currentNode => { return currentNode.get("id") === 7 })
- params
-
.sort(compare) Sorts a tree
- params
- compare(a:Node, b:Node) - comparison function
- return
null
- examples
function compareById(vector) { return (a, b) => { const aid = Number(a.get("id")) const bid = Number(b.get("id")) if (aid > bid) { return vector ? 1 : -1 } else if (aid < bid) { return vector ? -1 : 1 } else { return 0 } } } tree.sort(compareById(false)) //Desc
- params
-
.move(criteria, destination) Moves the desired branch or node to the node or branch of the destination, according to the criteria
- params
- criteria(Node) - callback
- destination(Node) - callback
- return
boolean
- examples
const search = currentNode => currentNode.get("id") === 7 const destination = currentNode => currentNode.get("id") === 3 const result = tree.move(search, destination)
- params
-
.traversal(criteria, callback) Bypasses the tree and, according to the criterion, calls a function for each node
- params
- criteria(Node) - return
boolean
- callback(Node)
- criteria(Node) - return
- return
null
- examples
const criteria = currentNode => currentNode.get("id") === 7 tree.traversal(criteria, currentNode => { currentNode.set("some", true) })
tree.traversal(null, currentNode => { if (currentNode.get("id") % 2 === 0) { currentNode.set("some", true) } })
- params
-
.toJson(options) Represents a tree in the form of a json format
- params
- options -
object
. Optional- empty_children - Type
boolean
. Allow empty children. Defaulttrue
- key_children - Type
string
. Field name for children. Defaultchildren
- empty_children - Type
- options -
- return
object
- examples
const json = tree.toJson()
- params
This is the node management class
- content Content of the node
- type
object
- type
- children Children of the node
- type
array
- type
- length Number children of the node
- type
number
- type
-
constructor(json)
- params
- json - simple
json
object
- json - simple
- examples
import JsTreeList from "js-tree-list" const rootContent = { id: 1, name: "Root" } let node = new JsTreeList.Node(rootContent)
- params
-
.add(child) Adding a child to the node
- return
Node
- created node - params
- child - type
object
/json
- child - type
- examples
const rootContent = { id: 1, name: "Root" } let node = new JsTreeList.Node(rootContent) const childNode = node.add({ id: 2, name: "Two node" })
- return
-
.remove(criteria) Removing a child node according to the criterion
- return - removed
Node
- params
- criteria - criteria function for removing nodes
- examples
const removedNodes = node.remove(itemNode => { return itemNode.get("id") === 3 })
- return - removed
-
.get(path) Access to node content by field name
- return
mixed
- params
- path - key name for object in node. For example
id
orfullname
, etc...
- path - key name for object in node. For example
- examples
node.get("id") // 1 node.get("name") // "Some name"
- return
-
.set(path, value) Setting a value or creating a new field in the contents of a node
- return
boolean
- params
- path -
String
field name - value -
mixed
- path -
- examples
node.set('id', 100)); // returned `true`. Node.content.id = 100 node.get('id'); // 100
- return
-
.sort(compare) Sorting child nodes
- return
null
- params
- compare - custom function for sorting
- examples
function compareById(vector) { return (a, b) => { const aid = Number(a.get("id")) const bid = Number(b.get("id")) if (aid > bid) { return vector ? 1 : -1 } else if (aid < bid) { return vector ? -1 : 1 } else { return 0 } } } node.sort(compareById(false))
- return
-
.traversal(criteria, callback) Bypassing child nodes according to the criterion and applying function to them
- return
null
- params
- criteria -
function
criteria each nodes - callback -
function
fire when criteria is true for node
- criteria -
- examples
// for all nodes node.traversal(null, currentNode => { const name = currentNode.get("name") currentNode.set("name", `${name}!`) // Last symbol "!" })
// only for node.id == 3 node.traversal( currentNode => currentNode.get("id") === 3, currentNode => { const name = currentNode.get("name") currentNode.set("name", `${name}!`) // Last symbol "!" } )
- return