树节点查找树的路径
const arr = [
{
id: '1',
children: [
{
id: '1.1',
children: [
{ id: '1.1.1', children: [] },
{ id: '1.1.2', children: [] },
]
},
{ id: '1.1', children: [] },
]
},
{
id: '1',
children: [
{ id: '1.3', children: [] },
{ id: '1.2', children: [] },
{ id: '1.2', children: [] },
]
},
{
id: '2',
children: [
{
id: '2.1',
children: [
{ id: '2.1.1', children: [] },
{ id: '2.1.2', children: [] },
]
},
{ id: '2.2', children: [] },
{ id: '2.2', children: [] },
]
}
]
/**
* 通过树节点查找树的路径
* @param findCode
* @return {*[]}
*/
const findTreeArr = (findCode, treeList, callback) => {
let resultList = []
const recursive = (findCode, path, data) => {
if (data.length === 0) {
return
}
for (const item of data) {
path.push(item)
if (item.id === findCode) {
resultList = JSON.parse(JSON.stringify(path))
return resultList
}
const children = Array.isArray(item.children) ? item.children : []
const result = recursive(findCode, path, children)
if (result) return result
path.pop()
}
return null
}
recursive(findCode, [], treeList)
return callback(resultList)
}
const x = findTreeArr('1.1.1', arr, (data) => (data.map(item => item.id)))
console.log(x)
数组队列组装成树
const arr = [
{ id: 1, name: '1' },
{ id: 2, name: '2' },
{ id: 3, name: '3' }
]
// 变为
const result = [
{
id: 1,
name: '1'
children: [
{
id: 2,
name: '2',
children: [
{
id: 3,
name: '3'
}
]
}
]
}
]
/**
* 将数组队列组装成树
* @param list
* @return {*}
*/
const arrayToTree = (list) => {
const obj = []
let cur = obj
const recursive = (path, data) => {
path.children = [{ ...data, children: [] }]
return path.children[0]
}
for (let i = 0; i < list.length; i++) {
cur = recursive(cur, list[i])
}
return obj['children']
}
树形结构合并相同节点
const arr = [
{
name: '1',
children: [
{
name: '1.1',
children: [
{ name: '1.1.1', children: [] },
{ name: '1.1.1', children: [] },
]
},
{ name: '1.1', children: [] },
]
},
{
name: '1',
children: [
{ name: '1.3', children: [] },
{ name: '1.2', children: [] },
{ name: '1.2', children: [] },
]
},
{
name: '2',
children: [
{
name: '2.1',
children: [
{ name: '2.1.1', children: [] },
{ name: '2.1.1', children: [] },
]
},
{ name: '2.2', children: [] },
{ name: '2.2', children: [] },
]
}
]
/**
* 树合并
* @param tree
* @return {*[]}
*/
const treeIterator = (tree) => {
const arr = []
if (!Array.isArray(tree) || !tree.length) return arr
tree.forEach((e) => {
const index = arr.findIndex(i => i.code === e.code)
if (index > -1) {
arr[index].children = treeIterator([...arr[index].children, ...e.children])
} else {
arr.push({ ...e, children: treeIterator(e.children) })
}
})
return arr
}
树形数组添加层级
/**
* 给树添加层级
* @param array
* @param levelName
* @param childrenName
* @return {*[]|*}
*/
export const arrayTreeAddLevel = (array, levelName = 'level', childrenName = 'child') => {
if (!Array.isArray(array)) return []
const recursive = (array, level = 0) => {
level++
return array.map(item => {
item[levelName] = level
const child = item[childrenName]
if (child && child.length) recursive(child, level)
return item
})
}
return recursive(array)
}
根据内容过滤树形数组
/**
* @description 根据内容过滤树形数组
* @param tree {[*]} tree的数组
* @param query {string} 搜索内容
* @param key {string} 对应树节点过滤的字段
* @param childrenName {string} 对应树节点children字段
* @return {[*]} 返回过滤后的树形数据
*/
export function filterTree(tree, query, key, childrenName = 'children') {
return tree
.map(node => {
const matchLabel = node[key].toLowerCase();
const queryLabel = query.toLowerCase()
const isMatch = matchLabel.includes(queryLabel);
const children = node[childrenName] ? filterTree(node[childrenName], queryLabel, key, childrenName) : [];
return isMatch || children.length > 0 ? { ...node, children } : null;
})
.filter(node => node !== null);
}
扁平数据结构转树结构
let arr = [
{id: 1, name: '部门1', pid: 0},
{id: 2, name: '部门2', pid: 1},
{id: 3, name: '部门3', pid: 1},
{id: 4, name: '部门4', pid: 3},
{id: 5, name: '部门5', pid: 4},
]
// 需要变成如下结构
[
{
"id": 1,
"name": "部门1",
"pid": 0,
"children": [
{
"id": 2,
"name": "部门2",
"pid": 1,
"children": []
},
{
"id": 3,
"name": "部门3",
"pid": 1,
"children": [
// 结果 ,,,
]
}
]
}
]
常规递归方法(时间复杂度为O(2^n)):
interface TreeNode {
id: number;
name: string;
pid: number;
children: TreeNode[];
}
type Tree = TreeNode[]
let arr: Omit<TreeNode, 'children'> = [
{id: 1, name: '部门1', pid: 0},
{id: 2, name: '部门2', pid: 1},
{id: 3, name: '部门3', pid: 1},
{id: 4, name: '部门4', pid: 3},
{id: 5, name: '部门5', pid: 4},
]
function getChildren(data: Tree, result: Tree, pid: number): void {
for (const item of data) {
if (pid === item.pid) {
const newTreeNode = { ...item, children: [] }
result.push(newTreeNode)
getChildren(data, newTreeNode.children, item.id)
}
}
}
Map存储借助遍历对象引用,从Map中查找对应数据(时间复杂度为O(2n),空间复杂度为O(n)):
function arrayToTreeMap(items: Tree, rootPid: number) {
const result = []; // 存放结果集
const itemMap: Record<string | number | symbol, TreeNode> = {};
// 先转成map存储
for (const item of items) {
itemMap[item.id] = { ...item, children: [] }
}
for (const item of items) {
const id = item.id;
const pid = item.pid;
const treeItem = itemMap[id];
if (pid === rootPid) {
result.push(treeItem);
} else {
if (!itemMap[pid]) {
itemMap[pid]['children'] = []
}
itemMap[pid].children.push(treeItem)
}
}
return result;
}
最佳解决方法(时间复杂度为O(n),空间复杂度为O(n)):
function arrayToTree(items) {
const result = []; // 存放结果集
const itemMap = {}; //
for (const item of items) {
const id = item.id;
const pid = item.pid;
if (!itemMap[id]) {
itemMap[id] = {
children: [],
}
}
itemMap[id] = {
...item,
children: itemMap[id]['children'] // 直接存储引用地址
}
const treeItem = itemMap[id];
if (pid === 0) {
result.push(treeItem);
} else {
if (!itemMap[pid]) {
itemMap[pid] = {
children: [],
}
}
itemMap[pid].children.push(treeItem)
}
}
return result;
}