Files
zmkgC/library/libUtils/slice_tree.go

250 lines
6.4 KiB
Go
Raw Permalink Normal View History

2025-07-07 20:11:59 +08:00
package libUtils
import (
"fmt"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"reflect"
)
// ParentSonSort 有层级关系的数组,父级-》子级 排序
func ParentSonSort(list g.List, params ...interface{}) g.List {
args := make([]interface{}, 8)
for k, v := range params {
if k == 8 {
break
}
args[k] = v
}
var (
pid int //父级id
level int //层级数
fieldName string //父级id键名
id string //id键名
levelName string //层级名称
title string //标题名称
breaks int //中断层级
prefixStr string //字符串前缀
)
pid = gconv.Int(GetSliceByKey(args, 0, 0))
level = gconv.Int(GetSliceByKey(args, 1, 0))
fieldName = gconv.String(GetSliceByKey(args, 2, "pid"))
id = gconv.String(GetSliceByKey(args, 3, "id"))
levelName = gconv.String(GetSliceByKey(args, 4, "flg"))
title = gconv.String(GetSliceByKey(args, 5, "title"))
breaks = gconv.Int(GetSliceByKey(args, 6, -1))
prefixStr = gconv.String(GetSliceByKey(args, 7, "─"))
//定义一个新slice用于返回
var returnSlice g.List
for _, v := range list {
if pid == gconv.Int(v[fieldName]) {
v[levelName] = level
levelClone := level
titlePrefix := ""
for {
if levelClone < 0 {
break
}
titlePrefix += prefixStr
levelClone--
}
titlePrefix = "├" + titlePrefix
if level == 0 {
v["title_prefix"] = ""
} else {
v["title_prefix"] = titlePrefix
}
v["title_show"] = fmt.Sprintf("%s%s", v["title_prefix"], v[title])
returnSlice = append(returnSlice, v)
if breaks != -1 && breaks == level {
continue
}
args[0] = v[id]
args[1] = level + 1
newSlice2 := ParentSonSort(list, args...)
if len(newSlice2) > 0 {
returnSlice = append(returnSlice, newSlice2...)
}
}
}
return returnSlice
}
// PushSonToParent 有层级关系的数组 ,将子级压入到父级(树形结构)
func PushSonToParent(list g.List, params ...interface{}) g.List {
args := make([]interface{}, 7)
for k, v := range params {
if k == 7 {
break
}
args[k] = v
}
var (
pid string //父级id
fieldName string //父级id键名
id string //id键名
key string //子级数组键名
filter string //过滤键名
filterVal interface{} //过滤的值
showNoChild bool //是否显示不存在的子级健
)
pid = gconv.String(GetSliceByKey(args, 0, 0))
fieldName = gconv.String(GetSliceByKey(args, 1, "pid"))
id = gconv.String(GetSliceByKey(args, 2, "id"))
key = gconv.String(GetSliceByKey(args, 3, "children"))
filter = gconv.String(GetSliceByKey(args, 4, ""))
filterVal = GetSliceByKey(args, 5, nil)
showNoChild = gconv.Bool(GetSliceByKey(args, 6, true))
var returnList g.List
for _, v := range list {
if gconv.String(v[fieldName]) == pid {
if filter != "" {
if reflect.DeepEqual(v[filter], filterVal) {
args[0] = v[id]
child := PushSonToParent(list, args...)
if child != nil || showNoChild {
v[key] = child
}
returnList = append(returnList, v)
}
} else {
args[0] = v[id]
child := PushSonToParent(list, args...)
if child != nil || showNoChild {
v[key] = child
}
returnList = append(returnList, v)
}
}
}
return returnList
}
// GetSliceByKey 获取切片里的值 若为nil 可设置默认值val
func GetSliceByKey(args []interface{}, key int, val interface{}) interface{} {
var value interface{}
if args[key] != nil {
value = args[key]
} else {
value = val
}
return value
}
// FindSonByParentId 有层级关系的切片通过父级id查找所有子级id数组
// parentId 父级id
// parentIndex 父级索引名称
// idIndex id索引名称
func FindSonByParentId(list g.List, parentId interface{}, parentIndex, idIndex string) g.List {
newList := make(g.List, 0, len(list))
for _, v := range list {
if reflect.DeepEqual(v[parentIndex], parentId) {
newList = append(newList, v)
fList := FindSonByParentId(list, v[idIndex], parentIndex, idIndex)
newList = append(newList, fList...)
}
}
return newList
}
// GetTopPidList 获取最顶层 parent Id
func GetTopPidList(list g.List, parentIndex, idIndex string) *garray.Array {
arr := garray.NewArray()
for _, v1 := range list {
tag := true
for _, v2 := range list {
if v1[parentIndex] == v2[idIndex] {
tag = false
break
}
}
if tag {
arr.PushRight(v1[parentIndex])
}
}
return arr.Unique()
}
// FindParentBySonPid 有层级关系的数组通过子级fid查找所有父级数组
func FindParentBySonPid(list g.List, id int, params ...interface{}) g.List {
args := make([]interface{}, 4)
for k, v := range params {
if k == 4 {
break
}
args[k] = v
}
var (
filter = gconv.String(GetSliceByKey(args, 0, "filter")) //过滤键名
fPid = gconv.String(GetSliceByKey(args, 1, "pid")) //父级id字段键名
filterValue = GetSliceByKey(args, 2, nil) //过滤键值
fid = gconv.String(GetSliceByKey(args, 3, "id")) //id字段键名
)
rList := make(g.List, 0, len(list))
for _, v := range list {
if gconv.Int(v[fid]) == id {
if fv, ok := v[filter]; ok {
if reflect.DeepEqual(fv, filterValue) {
rList = append(rList, v)
}
} else {
rList = append(rList, v)
}
r := FindParentBySonPid(list, gconv.Int(v[fPid]), filter, fPid, filterValue, fid)
rList = append(rList, r...)
}
}
return rList
}
// FindTopParent
/**
* 根据id查询最顶层父级信息
* @param list 有层级关系的数组
* @param id 查找的id
* @param string fpid 父级id键名
* @param string fid 当前id键名
* @return g.Map
*/
func FindTopParent(list g.List, id int64, params ...interface{}) g.Map {
if len(list) == 0 {
return g.Map{}
}
args := make([]interface{}, 2)
for k, v := range params {
if k == 2 {
break
}
args[k] = v
}
var (
fPid = gconv.String(GetSliceByKey(args, 0, "pid")) //父级id字段键名
fid = gconv.String(GetSliceByKey(args, 1, "id")) //id字段键名
)
hasParent := true
top := g.Map{}
//找到要查找id值的数组
for _, v := range list {
if gconv.Int64(v[fid]) == gconv.Int64(id) {
top = v
break
}
}
for {
if !hasParent {
break
}
//查询最顶层
for _, v := range list {
if gconv.Int64(top[fPid]) == gconv.Int64(v[fid]) {
top = v
hasParent = true
break
}
hasParent = false
}
}
return top
}