Files
wrapper/op_array/util.go
T

122 lines
3.9 KiB
Go

// Package op_array ...
//
// Description : op_array ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-11-25 11:30
package op_array
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/slice"
)
// ToMap 数组转map
func ToMap[Key comparable, Value any](dataList []Value, keyFormat func(item Value) Key) map[Key]Value {
return convertor.ToMap(dataList, func(item Value) (Key, Value) {
return keyFormat(item), item
})
}
// ToCustomMap 数组转map
func ToCustomMap[Key comparable, Value any, CustomValue any](dataList []Value, keyFormat func(item Value) Key, formatCustomValue func(item Value) CustomValue) map[Key]CustomValue {
return convertor.ToMap(dataList, func(item Value) (Key, CustomValue) {
return keyFormat(item), formatCustomValue(item)
})
}
// ExtractField 提取数组指定字段, 并构建成一个新的数组
func ExtractField[FieldValue any, Value any](dataList []Value, fieldValue func(item Value) FieldValue) []FieldValue {
return slice.Map(dataList, func(_ int, item Value) FieldValue {
return fieldValue(item)
})
}
// Filter 过滤列表数据
func Filter[Value any](dataList []Value, filterValue func(item Value) bool) []Value {
return slice.Filter(dataList, func(_ int, item Value) bool {
return filterValue(item)
})
}
// Group 按照指定字段进行分组
func Group[Key comparable, Value any](dataList []Value, keyFormat func(item Value) Key) [][]Value {
keyList := make([]string, 0)
dataTable := make(map[string][]Value)
res := make([][]Value, 0)
for _, item := range dataList {
key := fmt.Sprintf("%v", keyFormat(item))
if _, ok := dataTable[key]; !ok {
keyList = append(keyList, key)
}
dataTable[key] = append(dataTable[key], item)
}
formatList := make([][]Value, 0)
for _, key := range keyList {
formatList = append(formatList, dataTable[key])
}
return res
}
// GroupToMap 数组数据按照指定 key 进行分组
func GroupToMap[Key comparable, Value any](dataList []Value, keyFormat func(item Value) Key) map[Key][]Value {
return slice.GroupWith(dataList, func(item Value) Key {
return keyFormat(item)
})
}
// TreeItem 数据结构
type TreeItem[ID comparable, Value any] struct {
ID ID `json:"id" dc:"数据ID"`
ParentID ID `json:"parent_id" dc:"父级ID"`
Value Value `json:"value" dc:"数据值"`
ChildList []*TreeItem[ID, Value] `json:"child_list" dc:"子级数据列表"`
}
// Tree 将列表数据转为属性结构
func Tree[ID comparable, Value any](dataList []Value, formatParentID func(v Value) ID, formatID func(v Value) ID) *TreeItem[ID, Value] {
// list 转table
dataTable := make(map[ID]*TreeItem[ID, Value])
for _, item := range dataList {
dataID := formatID(item)
dataTable[dataID] = &TreeItem[ID, Value]{
ID: dataID,
ParentID: formatParentID(item),
Value: item,
ChildList: make([]*TreeItem[ID, Value], 0),
}
}
// 构建树(保证一定是一棵树)
rootData := &TreeItem[ID, Value]{
ID: *new(ID),
ParentID: *new(ID),
Value: *new(Value),
ChildList: make([]*TreeItem[ID, Value], 0), // 子数据列表
}
for _, item := range dataList {
dataID := formatID(item)
parentID := formatParentID(item)
if _, exist := dataTable[parentID]; exist {
// 归属某一个父级节点
dataTable[parentID].ChildList = append(dataTable[parentID].ChildList, dataTable[dataID])
} else {
// 部署于任何父节点, 则归属于虚拟的根节点
rootData.ChildList = append(rootData.ChildList, dataTable[dataID])
}
}
return rootData
}
// DeepClone 深度克隆一个数组, 每一个元素的地址均重新分配
func DeepClone[Value any](dataList []Value) []Value {
return convertor.DeepClone(dataList)
}
// Shard 将数组按照指定数量进行分片
func Shard[Value any](dataList []Value, itemShardCount int) [][]Value {
return slice.Chunk(dataList, itemShardCount)
}