001-Golang树型结构封装
日常问题001
注意:涉及到排序时,一般都是查库时就排好了,下面的操作不含排序实现
1.1 参数和返回值定义
这里的数据结构不使用 struct,用的 map,用什么我觉得都无所谓,根据具体情况来,反正最好还是用 struct 吧
// 核心数据结构-一般都是从数据库中获取的
var menus []map[string]interface{}
menu := map[string]interface{}{
"parentId": 0, // 父级id, 0表示当前菜单为最上级
"id": 1, // 菜单id
"name": "首页", // 菜单名称
}
// 返回值
var returnMenus []map[string]interface{}
returnMenu := map[string]interface{}{
"parentId": 0, // 父级id, 0表示当前菜单为最上级
"id": 1, // 菜单id
"name": "个人中心", // 菜单名称
"children": map[string]interface{}{
"parentId": 1,
"id": 2,
"name": "用户信息",
"children": map[string]interface{}{},
},
}
1.1 “最优解”(自我认可)
// 解题思想:都是地址操作,那么直接往父级地址塞
func getMenuTree(menus []map[string]interface{}) (realMenu []map[string]interface{}) {
if len(menus) < 1 {
return nil
}
formatMenu := make(map[int]map[string]interface{})
for _, m := range menus {
formatMenu[m["id"].(int)] = m
if m["parentId"].(int) == 0 {
realMenu = append(realMenu, m) // 需要返回的顶级菜单
}
}
// 得益于都是地址操作,可以直接往父级塞
for _, m := range formatMenu {
if formatMenu[m["parentId"].(int)] == nil {
continue
}
if formatMenu[m["parentId"].(int)]["children"] == nil {
formatMenu[m["parentId"].(int)]["children"] = []map[string]interface{}{}
}
formatMenu[m["parentId"].(int)]["children"] = append(formatMenu[m["parentId"].(int)]["children"].([]map[string]interface{}), m)
}
return
}
1.2 蠢笨解
蠢笨蠢笨的操作,没有使用地址,也不使用递归
// 解题思路:先将菜单按层级分,然后一层一层往上封装
func getMenuTree(menus []map[string]interface{}) (realMenu []map[string]interface{}) {
if len(menus) < 1 {
return nil
}
// 临时存储当前层级所以子层级的菜单,比如:获取第一级时,tmp存储的就是二级及以下的菜单
var tmp []map[string]interface{}
// 储存格式 [level:[menuID:[menuInfo]]]
formatMenu := make(map[int]map[int]map[string]interface{})
level := 1
// 按照菜单层级进行分组
for {
if len(menus) < 1 {
break
}
for _, m := range menus {
if formatMenu[level] == nil {
formatMenu[level] = make(map[int]map[string]interface{})
}
// 第一次时,上级都为空;第二次时,都没有parentId=0的数据了
if m["parentId"].(int) == 0 || formatMenu[level-1][m["parentId"].(int)] != nil {
formatMenu[level][m["id"].(int)] = m
} else {
tmp = append(tmp, m)
}
}
level++
menus = tmp
tmp = nil
}
// 组装为树型结构
var parentMenu map[string]interface{}
// 存储格式:[menuID:[menuInfo]]
var selfMenus map[int]map[string]interface{}
for i := level - 1; i > 1; i-- {
selfMenus = formatMenu[i]
// 如果查询没有进行排序,那么这里需要进行排序-但这里并未实现
for _, selfMenu := range selfMenus {
parentMenu = formatMenu[i-1][selfMenu["parentId"].(int)]
if parentMenu == nil {
continue
}
if parentMenu["children"] == nil {
parentMenu["children"] = []map[string]interface{}{}
}
parentMenu["children"] = append(parentMenu["children"].([]map[string]interface{}), selfMenu)
}
}
// 取第一级菜单,并将map[int]map[string]interface{}转化为[]map[string]interface{}
for _, m := range formatMenu[1] {
realMenu = append(realMenu, m)
}
formatMenu = nil
return
}
1.3 递归解
注意 stackoverflow
// 递归,无话可说
func getMenuTree(parentId float64, menus *[]map[string]interface{}) (childrenList []map[string]interface{}) {
if len(*menus) < 1 {
return nil
}
for _, systemMenu := range *menus {
if systemMenu["parentId"].(float64) == parentId {
systemMenu["children"] = getMenuTree(systemMenu["id"].(float64), menus)
childrenList = append(childrenList, systemMenu)
}
}
return
}