数组转 tree目前发现就三种方式,js版本实现了三种,go实现了两种
-
递归模式
-
双重循环
-
map特性模式(这种模式我在go中实验了几次都没成功,有大佬成功告知一下)
js版本
let arr = [{name: "李四", id: 2, pid: 0},// []
{name: "王五", id: 3, pid: 0}, // []
{name: "赵六", id: 4, pid: 3}, // []
{name: "吗六", id: 9, pid: 3}, // []
{name: "张三", id: 7, pid: 9}, // []
{name: "张五", id: 10, pid: 4}, // []
]
/**
* 递归模式,数组转tree
* @param arr 目标数组
* @param pid 第一级 目标id
* @returns {*[]} tree
* [
* { name: '李四', id: 2, pid: 0, children: [] },
* { name: '王五', id: 3, pid: 0, children: [ [Object], [Object] ] }
* ]
* @constructor
*/
function ArrayToTree(arr, pid = 0) {
// 判断是否是数组 不是数组就返回 []
if (!Array.isArray(arr) || !arr.length) return [];
let newArr = []
arr.forEach(item => {
// 判断 当前item.pid 和 传入的pid 是否相等,相等就push 进去
if (item.pid == pid) {
newArr.push({
...item, children: ArrayToTree(arr, item.id)
})
}
})
return newArr
}
/**
* map模式 ,数组转tree
* @param arr 目标数组
* @param pid 第一级 目标id
* @returns {*[]}
* [
* { name: '李四', id: 2, pid: 0 },
* { name: '王五', id: 3, pid: 0, child: [ [Object], [Object] ] }
* ]
* @constructor
*/
function ArrAyToTreeMap(arr,pid=0) {
if (!Array.isArray(arr) || !arr.length) return [];
let map = {}
// 把map的key 是item.id value是item
arr.forEach(item => map[item.id] = item)
let res = []
arr.forEach(item => {
// item.pid 和 map的key 是否存在, 存在就 true 不存在就false
let mapPid = map[item.pid]
// 把pid顶级相等的插入进去
if (item.pid == pid){
res.push(item)
}else {
if (mapPid) {
// 存在就 判断 map的child 是否存在 ,不存在就赋值一个数组,在添加 item
((mapPid.child || (mapPid.child = [])).push(item))
}
}
})
return res;
}
/**
* 过滤器的模式,数组转tree
* @param arr
* @returns [] 数组对象的 tree , 有需要自己在 过滤一下指定的 pid
* [
* { name: '李四', id: 2, pid: 0, children: [] },
* { name: '王五', id: 3, pid: 0, children: [ [Object], [Object] ] }
* ]
*/
function arrToTreeArray(arr,pid=0){
if (!Array.isArray(arr) || !arr.length) return [];
// 克隆一个新数组
let copyArr = arr.filter(item =>{
let children = arr.filter(v => item.id === v.pid)
item.children = children.length > 0 ? item.children = children : []
if (item.pid == pid){
return item
}
})
return copyArr
}
/**
* 双重for循环模式,数组转tree
* @param arr
* @returns {any}
* [
* { name: '李四', id: 2, pid: 0 },
* { name: '王五', id: 3, pid: 0, children: [ [Object], [Object] ] }
* ]
*/
function arrToTreeOne(arr,pid=0){
if (!Array.isArray(arr) || !arr.length) return [];
// 克隆一个新数组
let copyArr = Object.assign([],arr)
// 双重循环
let newArr = copyArr.filter(item =>{
arr.forEach(v =>{
// 判断 id 和 pid 是否相同
if(item.id === v.pid){
// 相同就判断有没有 children , 有就push进去v 没有就 [v]
if(item.children){
item.children.push(v)
}else{
item.children = [v]
}
}
})
if (item.pid == pid) return item
})
return newArr
}
console.log(ArrayToTree(arr))
go版本
// List 结构体
type List struct {
Name string `json:"name"`
Id int `json:"id"`
Pid int `json:"pid"`
Children []List `json:"children"`
}
// 数据
var data = []List{
{Name: "李四", Id: 2, Pid: 0}, // []
{Name: "王五", Id: 3, Pid: 0}, // []
{Name: "赵六", Id: 4, Pid: 3}, // []
{Name: "吗六", Id: 9, Pid: 3}, // []
{Name: "张三", Id: 7, Pid: 9}, // []
{Name: "张五", Id: 10, Pid: 4}, // []
}
/**
* 递归模式,数组转tree
* @param arr 目标数组
* @param pid 第一级 目标id
* @returns {*[]} tree
* @constructor
*/
func ArrayToTree(arr []List, pid int) []List {
var newArr []List
for _, v := range arr {
if v.Pid == pid {
v.Children = ArrayToTree(arr, v.Id)
newArr = append(newArr, v)
}
}
return newArr
}
/**
* 双重for循环模式,数组转tree
* @param arr
* @returns {any}
* [
* { name: '李四', id: 2, pid: 0 },
* { name: '王五', id: 3, pid: 0, children: [ [Object], [Object] ] }
* ]
*/
func arrToTreeArray(arr []List, pid int) []List {
var res = arr
for i, item := range arr {
var newArr = []List{}
for _, v := range arr {
if item.Id == v.Pid {
newArr = append(newArr, v)
}
}
res[i].Children = newArr
}
var result []List
for _, item := range res {
if item.Pid == pid {
result = append(result, item)
}
}
return result
}