preface
Data manipulation of tree structure is a necessary skill for a developer. In the actual business development, we will also encounter many tree structures, such as the most common regional tree, enterprise structure tree, school level organization tree and so on.
The following is a series of operation methods about JavaScript tree. Combined with examples, I believe you will use them more or less in actual development work.
Flatten arrays
Example
const arr = [1, [2, [3, 4]], 5, [6]];
method
1. Recursion
const flatten = (arr) => { let res = []; arr.map(item => { if(Array.isArray(item)) { res = res.concat(flatten(item)); } else { res.push(item); } }); return res; }
2,reduce
const flatten = (arr) => { return arr.reduce((result, item)=> { return result.concat(Array.isArray(item) ? flatten(item) : item); }, []); }
3,flat
const flatten = (arr) => { return arr.flat(Infinity) }
Operation results
const result = flatten(arr); console.log(result); // Operation results [1, 2, 3, 4, 5, 6]
Array to tree structure
Example
const arr = [ { name: 'Xiao Ming', id: 1, pid: 0, }, { name: 'floret', id: 11, pid: 1, }, { name: 'Xiaohua', id: 111, pid: 11, }, { name: 'petty thief', id: 112, pid: 11, }, { name: 'Xiao Hong', id: 12, pid: 1, }, { name: 'Xiao Wang', id: 2, pid: 0, }, { name: 'Kobayashi', id: 21, pid: 2, }, { name: 'petty thief', id: 22, pid: 2, } ]
method
1. Non recursive
const arrayToTree = (arr) => { let result = []; if (!Array.isArray(arr) || arr.length === 0) { return result } let map = {}; arr.forEach(item => map[item.id] = item); arr.forEach(item => { const parent = map[item.pid]; if(parent){ (parent.children || (parent.children=[])).push(item); } else { result.push(item); } }) return result }
2. Recursion
const arrayToTree = (arr, pid) => { let res = []; arr.forEach(item => { if(item.pid === pid){ let itemChildren = arrayToTree(arr,item.id); if(itemChildren.length) { item.children = itemChildren; } res.push(item); } }); return res; }
Operation results
// const result = arrayToTree(arr); const result = arrayToTree(arr, 0); console.log(result); // Operation results [ { "name": "Xiao Ming", "id": 1, "pid": 0, "children": [ { "name": "floret", "id": 11, "pid": 1, "children": [ { "name": "Xiaohua", "id": 111, "pid": 11 }, { "name": "petty thief", "id": 112, "pid": 11 } ] }, { "name": "Xiao Hong", "id": 12, "pid": 1 } ] }, { "name": "Xiao Wang", "id": 2, "pid": 0, "children": [ { "name": "Kobayashi", "id": 21, "pid": 2 }, { "name": "petty thief", "id": 22, "pid": 2 } ] } ]
Tree structure to array (flattening)
Example
const tree = [ { name: 'Xiao Ming', id: 1, pid: 0, children: [ { name: 'floret', id: 11, pid: 1, children: [ { name: 'Xiaohua', id: 111, pid: 11, }, { name: 'petty thief', id: 112, pid: 11, } ] }, { name: 'Xiao Hong', id: 12, pid: 1, } ] }, { name: 'Xiao Wang', id: 2, pid: 0, children: [ { name: 'Kobayashi', id: 21, pid: 2, }, { name: 'petty thief', id: 22, pid: 2, } ] } ]
method
1. Depth first traversal
const treeToArray = (tree) => { let stack = tree, result = []; while(stack.length !== 0){ let pop = stack.pop(); result.push({ id: pop.id, name: pop.name, pid: pop.pid }) let children = pop.children if(children){ for(let i = children.length-1; i >=0; i--){ stack.push(children[i]) } } } return result }
2. Breadth first traversal
const treeToArray = (tree) => { let queue = tree, result = []; while(queue.length !== 0){ let shift = queue.shift(); result.push({ id: shift.id, name: shift.name, pid: shift.pid }) let children = shift.children if(children){ for(let i = 0; i < children.length; i++){ queue.push(children[i]) } } } return result }
3. Do not consider other attributes except children
const treeToArray = (source)=>{ let res = [] source.forEach(item=>{ res.push(item) item.children && res.push(...treeToArray(item.children)) }) return res.map((item) => { if (item.children) { delete item.children } return item }) }
Operation results
const result = treeToArray(tree); console.log(result); // Operation results [ { "name": "Xiao Ming", "id": 1, "pid": 0 }, { "name": "floret", "id": 11, "pid": 1 }, { "name": "Xiaohua", "id": 111, "pid": 11 }, { "name": "petty thief", "id": 112, "pid": 11 }, { "name": "Xiao Hong", "id": 12, "pid": 1 }, { "name": "Xiao Wang", "id": 2, "pid": 0 }, { "name": "Kobayashi", "id": 21, "pid": 2 }, { "name": "petty thief", "id": 22, "pid": 2 } ]
Tree filter, retain the qualified data and return the tree structure
Example
const tree = [ { name: 'Xiao Ming', id: 1, pid: 0, show: true, children: [ { name: 'floret', id: 11, pid: 1, show: true, children: [ { name: 'Xiaohua', id: 111, pid: 11, }, { name: 'petty thief', id: 112, pid: 11, show: true, } ] }, { name: 'Xiao Hong', id: 12, pid: 1, } ] }, { name: 'Xiao Wang', id: 2, pid: 0, show: true, children: [ { name: 'Kobayashi', id: 21, pid: 2, }, { name: 'petty thief', id: 22, pid: 2, } ] } ]
method
Filter out data with show as true
const filterTreeByFunc = (tree, func) => { if (!Array.isArray(tree) || tree.length === 0) { return [] } return tree.filter(item => { item.children = item.children && filterTreeByFunc(item.children, func) return func(item) || (item.children && item.children.length) }) } const func = (item) => { return item.show === true }
Operation results
const result = filterTreeByFunc(tree, func); console.log(result); // Operation results [ { "name": "Xiao Ming", "id": 1, "pid": 0, "show": true, "children": [ { "name": "floret", "id": 11, "pid": 1, "show": true, "children": [ { "name": "petty thief", "id": 112, "pid": 11, "show": true } ] } ] }, { "name": "Xiao Wang", "id": 2, "pid": 0, "show": true, "children": [] } ]
Find the path of a node in the tree
Example
const tree = [ { name: 'Xiao Ming', id: 1, pid: 0, children: [ { name: 'floret', id: 11, pid: 1, children: [ { name: 'Xiaohua', id: 111, pid: 11, }, { name: 'petty thief', id: 112, pid: 11, } ] }, { name: 'Xiao Hong', id: 12, pid: 1, } ] }, { name: 'Xiao Wang', id: 2, pid: 0, children: [ { name: 'Kobayashi', id: 21, pid: 2, }, { name: 'petty thief', id: 22, pid: 2, } ] } ]
method
const getNodePath = (tree, id) => { if (!Array.isArray(tree) || tree.length === 0) { return [] } const path = [] const treeFindPath = (tree, id, path) => { for (const item of tree) { path.push(item.id); if (item.id === id) { return path } if (item.children) { const findChildren = treeFindPath(item.children,id, path); if (findChildren.length) { return findChildren; } } path.pop(); } return []; } return treeFindPath(tree, id, path) }
Operation results
const result = getNodePath(tree, 112); console.log(result); // Operation results [1, 11, 112]
Fuzzy query tree
Example
const tree = [ { name: 'Xiaoming front-end expert', id: 1, pid: 0, children: [ { name: 'Xiaohua front end program yuan', id: 11, pid: 1, children: [ { name: 'Xiaohua rower', id: 111, pid: 11, }, { name: 'Xiao Li fisherman', id: 112, pid: 11, } ] }, { name: 'Little red fishing programmer', id: 12, pid: 1, } ] }, { name: 'Xiao Wang, inner scroll King', id: 2, pid: 0, children: [ { name: 'Kobayashi fishing king', id: 21, pid: 2, }, { name: 'Xiao Li back-end programmer', id: 22, pid: 2, } ] } ]
method
const fuzzyQueryTree = (arr, value) => { if (!Array.isArray(arr) || arr.length === 0) { return [] } let result = []; arr.forEach(item => { if (item.name.indexOf(value) > -1) { const children = fuzzyQueryTree(item.children, value); const obj = { ...item, children } result.push(obj); } else { if (item.children && item.children.length > 0) { const children = fuzzyQueryTree(item.children, value); const obj = { ...item, children } if (children && children.length > 0) { result.push(obj); } } } }); return result; };
Operation results
const result = fuzzyQueryTree(tree,'program'); console.log(result); // Operation results [ { "name": "Xiaoming front-end expert", "id": 1, "pid": 0, "children": [ { "name": "Xiaohua front end program yuan", "id": 11, "pid": 1, "children": [] }, { "name": "Little red fishing programmer", "id": 12, "pid": 1, "children": [] } ] }, { "name": "Xiao Wang, inner scroll King", "id": 2, "pid": 0, "children": [ { "name": "Xiao Li back-end programmer", "id": 22, "pid": 2, "children": [] } ] } ]
Add attributes to tree nodes
Example
const tree = [ { name: 'Xiao Ming', id: 1, pid: 0, children: [ { name: 'floret', id: 11, pid: 1, children: [ { name: 'Xiaohua', id: 111, pid: 11, }, { name: 'petty thief', id: 112, pid: 11, } ] }, { name: 'Xiao Hong', id: 12, pid: 1, } ] }, { name: 'Xiao Wang', id: 2, pid: 0, children: [ { name: 'Kobayashi', id: 21, pid: 2, }, { name: 'petty thief', id: 22, pid: 2, } ] } ]
method
const addAttrToNodes = (tree) => { tree.forEach((item) => { item.title = 'New generation of migrant workers' if (item.children && item.children.length > 0) { addAttrToNodes(item.children) } }) return tree }
Operation results
const result = addAttrToNodes(tree); console.log(result); // Operation results [ { "name": "Xiao Ming", "id": 1, "pid": 0, "children": [ { "name": "floret", "id": 11, "pid": 1, "children": [ { "name": "Xiaohua", "id": 111, "pid": 11, "title": "New generation of migrant workers" }, { "name": "petty thief", "id": 112, "pid": 11, "title": "New generation of migrant workers" } ], "title": "New generation of migrant workers" }, { "name": "Xiao Hong", "id": 12, "pid": 1, "title": "New generation of migrant workers" } ], "title": "New generation of migrant workers" }, { "name": "Xiao Wang", "id": 2, "pid": 0, "children": [ { "name": "Kobayashi", "id": 21, "pid": 2, "title": "New generation of migrant workers" }, { "name": "petty thief", "id": 22, "pid": 2, "title": "New generation of migrant workers" } ], "title": "New generation of migrant workers" } ]
Tree node delete attribute
Example
Here, you can directly use the operation result of adding attributes to the tree structure node
method
const removeAttrFromNode = (tree) => { tree.forEach((item) => { delete item.title if (item.children && item.children.length > 0) { removeAttrFromNode(item.children) } }) return tree }
Operation results
const result = removeAttrFromNode(tree); console.log(result); // Operation results [ { "name": "Xiao Ming", "id": 1, "pid": 0, "children": [ { "name": "floret", "id": 11, "pid": 1, "children": [ { "name": "Xiaohua", "id": 111, "pid": 11 }, { "name": "petty thief", "id": 112, "pid": 11 } ] }, { "name": "Xiao Hong", "id": 12, "pid": 1 } ] }, { "name": "Xiao Wang", "id": 2, "pid": 0, "children": [ { "name": "Kobayashi", "id": 21, "pid": 2 }, { "name": "petty thief", "id": 22, "pid": 2 } ] } ]
Delete empty children in the tree
Example
const tree = [ { name: 'Xiao Ming', id: 1, pid: 0, children: [ { name: 'floret', id: 11, pid: 1, children: [ { name: 'Xiaohua', id: 111, pid: 11, }, { name: 'petty thief', id: 112, pid: 11, children: [] } ] }, { name: 'Xiao Hong', id: 12, pid: 1, children: [] } ] }, { name: 'Xiao Wang', id: 2, pid: 0, children: [ { name: 'Kobayashi', id: 21, pid: 2, }, { name: 'petty thief', id: 22, pid: 2, children: [] } ] } ]
method
const removeEmptyChildren = (tree) => { tree.forEach((item) => { if (item.children && item.children.length ===0) { delete item.children } else if (item.children && item.children.length > 0) { removeEmptyChildren(item.children) } }) return tree }
Operation results
const result = removeEmptyChildren(tree); console.log(result); // Operation results [ { "name": "Xiao Ming", "id": 1, "pid": 0, "children": [ { "name": "floret", "id": 11, "pid": 1, "children": [ { "name": "Xiaohua", "id": 111, "pid": 11 }, { "name": "petty thief", "id": 112, "pid": 11 } ] }, { "name": "Xiao Hong", "id": 12, "pid": 1 } ] }, { "name": "Xiao Wang", "id": 2, "pid": 0, "children": [ { "name": "Kobayashi", "id": 21, "pid": 2 }, { "name": "petty thief", "id": 22, "pid": 2 } ] } ]
Get all leaf nodes in the tree
Example
const tree = [ { name: 'Xiao Ming', id: 1, pid: 0, children: [ { name: 'floret', id: 11, pid: 1, children: [ { name: 'Xiaohua', id: 111, pid: 11, }, { name: 'petty thief', id: 112, pid: 11, } ] }, { name: 'Xiao Hong', id: 12, pid: 1, } ] }, { name: 'Xiao Wang', id: 2, pid: 0, children: [ { name: 'Kobayashi', id: 21, pid: 2, }, { name: 'petty thief', id: 22, pid: 2, } ] } ]
method
const getAllLeaf = (tree) => { const result = [] const getLeaf = (tree) => { tree.forEach((item) => { if (!item.children) { result.push(item) } else { getLeaf(item.children) } }) } getLeaf(tree) return result }
Operation results
const result = getAllLeaf(tree); console.log(result); // Operation results [ { "name": "Xiaohua", "id": 111, "pid": 11 }, { "name": "petty thief", "id": 112, "pid": 11 }, { "name": "Xiao Hong", "id": 12, "pid": 1 }, { "name": "Kobayashi", "id": 21, "pid": 2 }, { "name": "petty thief", "id": 22, "pid": 2 } ]
reference resources
https://wintc.top/article/20
https://www.cnblogs.com/mengff/p/13142128.html
https://blog.csdn.net/susuzhe123/article/details/95353403
https://blog.csdn.net/web_yueqiang/article/details/89483971
last
This paper arranges a series of operation methods of JavaScript tree, which is equivalent to a summary at ordinary times. You can use it immediately or make reference and modification according to the actual business.
If you have a better implementation method, or you encounter something in your development, but it is not involved in the above, you are welcome to put it forward, discuss it and make progress together~