// Package op_array ... // // Description : op_array ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2025-11-25 11:30 package op_array import ( "fmt" "reflect" ) // ToMap 数组转map func ToMap[Key comparable, Value any](dataList []Value, keyFormat func(item Value) Key) map[Key]Value { res := make(map[Key]Value) for _, item := range dataList { key := keyFormat(item) res[key] = item } return res } // 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 { res := make(map[Key]CustomValue) for _, item := range dataList { key := keyFormat(item) res[key] = formatCustomValue(item) } return res } // ExtractField 提取数组指定字段, 并构建成一个新的数组 func ExtractField[FieldValue any, Value any](dataList []Value, fieldValue func(item Value) FieldValue) []FieldValue { res := make([]FieldValue, 0) for _, item := range dataList { v := fieldValue(item) res = append(res, v) } return res } // Filter 过滤列表数据 func Filter[Value any](dataList []Value, filterValue func(item Value) bool) []Value { res := make([]Value, 0) for _, item := range dataList { if filterValue(item) { res = append(res, item) } } return res } // 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 } // 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 { v := *new(Value) vType := reflect.TypeOf(v) res := make([]Value, len(dataList)) for i := 0; i < len(dataList); i++ { newV := new(Value) switch vType.Kind() { case reflect.Ptr: // 解引用, 并单独读取值后重新分配地址 copyV := reflect.New(vType.Elem()).Elem() copyV.Set(reflect.ValueOf(dataList[i]).Elem()) *newV = copyV.Addr().Interface().(Value) case reflect.Map: mapVal := reflect.ValueOf(dataList[i]) mapKeyList := mapVal.MapKeys() newMap := reflect.MakeMap(vType) for _, key := range mapKeyList { // 通过键获取对应的值 value := mapVal.MapIndex(key) newMap.SetMapIndex(key, value) } *newV = newMap.Interface().(Value) default: *newV = dataList[i] } res[i] = *newV } return res } // Shard 将数组按照指定数量进行分片 func Shard[Value any](dataList []Value, itemShardCount int) [][]Value { res := make([][]Value, 0) for i := 0; i < len(dataList); i += itemShardCount { tmpList := make([]Value, 0) for j := 0; j < itemShardCount; j++ { tmpList = append(tmpList, dataList[i+j]) } res = append(res, tmpList) } return res }