Initial QSfera import
This commit is contained in:
+279
@@ -0,0 +1,279 @@
|
||||
package maputil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/arrutil"
|
||||
"github.com/gookit/goutil/comdef"
|
||||
"github.com/gookit/goutil/reflects"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
// alias functions
|
||||
var (
|
||||
// ToStrMap convert map[string]any to map[string]string
|
||||
ToStrMap = ToStringMap
|
||||
// ToL2StrMap convert map[string]any to map[string]map[string]string
|
||||
ToL2StrMap = ToL2StringMap
|
||||
)
|
||||
|
||||
// KeyToLower convert keys to lower case.
|
||||
func KeyToLower(src map[string]string) map[string]string {
|
||||
if len(src) == 0 {
|
||||
return src
|
||||
}
|
||||
|
||||
newMp := make(map[string]string, len(src))
|
||||
for k, v := range src {
|
||||
k = strings.ToLower(k)
|
||||
newMp[k] = v
|
||||
}
|
||||
return newMp
|
||||
}
|
||||
|
||||
// AnyToStrMap try convert any(map[string]any, map[string]string) to map[string]string
|
||||
func AnyToStrMap(src any) map[string]string {
|
||||
if src == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if m, ok := src.(map[string]string); ok {
|
||||
return m
|
||||
}
|
||||
if m, ok := src.(map[string]any); ok {
|
||||
return ToStringMap(m)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToStringMap simple convert map[string]any to map[string]string
|
||||
func ToStringMap(src map[string]any) map[string]string {
|
||||
strMp := make(map[string]string, len(src))
|
||||
for k, v := range src {
|
||||
strMp[k] = strutil.SafeString(v)
|
||||
}
|
||||
return strMp
|
||||
}
|
||||
|
||||
// ToL2StringMap convert map[string]any to map[string]map[string]string
|
||||
func ToL2StringMap(groupsMap map[string]any) map[string]map[string]string {
|
||||
if len(groupsMap) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
l2sMap := make(map[string]map[string]string, len(groupsMap))
|
||||
|
||||
for k, v := range groupsMap {
|
||||
if mp, ok := v.(map[string]any); ok {
|
||||
l2sMap[k] = ToStringMap(mp)
|
||||
} else if smp, ok := v.(map[string]string); ok {
|
||||
l2sMap[k] = smp
|
||||
}
|
||||
}
|
||||
return l2sMap
|
||||
}
|
||||
|
||||
// CombineToSMap combine two string-slices to SMap(map[string]string)
|
||||
func CombineToSMap(keys, values []string) SMap {
|
||||
return arrutil.CombineToSMap(keys, values)
|
||||
}
|
||||
|
||||
// CombineToMap combine two any slice to map[K]V. alias of arrutil.CombineToMap
|
||||
func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V {
|
||||
return arrutil.CombineToMap(keys, values)
|
||||
}
|
||||
|
||||
// SliceToSMap convert string k-v pairs slice to map[string]string
|
||||
// - eg: []string{k1,v1,k2,v2} -> map[string]string{k1:v1, k2:v2}
|
||||
func SliceToSMap(kvPairs ...string) map[string]string {
|
||||
ln := len(kvPairs)
|
||||
// check kvPairs length must be even
|
||||
if ln == 0 || ln%2 != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sMap := make(map[string]string, ln/2)
|
||||
for i := 0; i < ln; i += 2 {
|
||||
sMap[kvPairs[i]] = kvPairs[i+1]
|
||||
}
|
||||
return sMap
|
||||
}
|
||||
|
||||
// SliceToMap convert any k-v pairs slice to map[string]any
|
||||
func SliceToMap(kvPairs ...any) map[string]any {
|
||||
ln := len(kvPairs)
|
||||
// check kvPairs length must be even
|
||||
if ln == 0 || ln%2 != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
mp := make(map[string]any, ln/2)
|
||||
for i := 0; i < ln; i += 2 {
|
||||
kStr := strutil.SafeString(kvPairs[i])
|
||||
mp[kStr] = kvPairs[i+1]
|
||||
}
|
||||
return mp
|
||||
}
|
||||
|
||||
// SliceToTypeMap convert k-v pairs slice to map[string]T
|
||||
func SliceToTypeMap[T any](valFunc func(any) T, kvPairs ...any) map[string]T {
|
||||
ln := len(kvPairs)
|
||||
// check kvPairs length must be even
|
||||
if ln == 0 || ln%2 != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
mp := make(map[string]T, ln/2)
|
||||
for i := 0; i < ln; i += 2 {
|
||||
kStr := strutil.SafeString(kvPairs[i])
|
||||
mp[kStr] = valFunc(kvPairs[i+1])
|
||||
}
|
||||
return mp
|
||||
}
|
||||
|
||||
// ToAnyMap convert map[TYPE1]TYPE2 to map[string]any
|
||||
func ToAnyMap(mp any) map[string]any {
|
||||
amp, _ := TryAnyMap(mp)
|
||||
return amp
|
||||
}
|
||||
|
||||
// TryAnyMap convert map[TYPE1]TYPE2 to map[string]any
|
||||
func TryAnyMap(mp any) (map[string]any, error) {
|
||||
if aMp, ok := mp.(map[string]any); ok {
|
||||
return aMp, nil
|
||||
}
|
||||
if sMp, ok := mp.(map[string]string); ok {
|
||||
anyMp := make(map[string]any, len(sMp))
|
||||
for k, v := range sMp {
|
||||
anyMp[k] = v
|
||||
}
|
||||
return anyMp, nil
|
||||
}
|
||||
|
||||
rv := reflect.Indirect(reflect.ValueOf(mp))
|
||||
if rv.Kind() != reflect.Map {
|
||||
return nil, errors.New("input is not a map value type")
|
||||
}
|
||||
|
||||
anyMp := make(map[string]any, rv.Len())
|
||||
for _, key := range rv.MapKeys() {
|
||||
keyStr := strutil.SafeString(key.Interface())
|
||||
anyMp[keyStr] = rv.MapIndex(key).Interface()
|
||||
}
|
||||
return anyMp, nil
|
||||
}
|
||||
|
||||
// HTTPQueryString convert map[string]any data to http query string.
|
||||
func HTTPQueryString(data map[string]any) string {
|
||||
ss := make([]string, 0, len(data))
|
||||
for k, v := range data {
|
||||
ss = append(ss, k+"="+strutil.QuietString(v))
|
||||
}
|
||||
|
||||
return strings.Join(ss, "&")
|
||||
}
|
||||
|
||||
// StringsMapToAnyMap convert map[string][]string to map[string]any
|
||||
//
|
||||
// Example:
|
||||
// {"k1": []string{"v1", "v2"}, "k2": []string{"v3"}}
|
||||
// =>
|
||||
// {"k": []string{"v1", "v2"}, "k2": "v3"}
|
||||
//
|
||||
// mp := StringsMapToAnyMap(httpReq.Header)
|
||||
func StringsMapToAnyMap(ssMp map[string][]string) map[string]any {
|
||||
if len(ssMp) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
anyMp := make(map[string]any, len(ssMp))
|
||||
for k, v := range ssMp {
|
||||
if len(v) == 1 {
|
||||
anyMp[k] = v[0]
|
||||
continue
|
||||
}
|
||||
anyMp[k] = v
|
||||
}
|
||||
return anyMp
|
||||
}
|
||||
|
||||
// ToString simple and quickly convert map[string]any to string.
|
||||
func ToString(mp map[string]any) string {
|
||||
if mp == nil {
|
||||
return ""
|
||||
}
|
||||
if len(mp) == 0 {
|
||||
return "{}"
|
||||
}
|
||||
|
||||
buf := make([]byte, 0, len(mp)*16)
|
||||
buf = append(buf, '{')
|
||||
|
||||
for k, val := range mp {
|
||||
buf = append(buf, k...)
|
||||
buf = append(buf, ':')
|
||||
|
||||
str := strutil.QuietString(val)
|
||||
buf = append(buf, str...)
|
||||
buf = append(buf, ',', ' ')
|
||||
}
|
||||
|
||||
// remove last ', '
|
||||
buf = append(buf[:len(buf)-2], '}')
|
||||
return strutil.Byte2str(buf)
|
||||
}
|
||||
|
||||
// ToString2 simple and quickly convert a map to string.
|
||||
func ToString2(mp any) string { return NewFormatter(mp).Format() }
|
||||
|
||||
// FormatIndent format map data to string with newline and indent.
|
||||
func FormatIndent(mp any, indent string) string {
|
||||
return NewFormatter(mp).WithIndent(indent).Format()
|
||||
}
|
||||
|
||||
// StrMapToText 将 map[string]string 转换为多行 key=value 格式文本
|
||||
func StrMapToText(m map[string]string) string {
|
||||
if len(m) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var lines []string
|
||||
for key, value := range m {
|
||||
lines = append(lines, key+"="+value)
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* Flat convert tree map to flatten key-value map.
|
||||
*************************************************************/
|
||||
|
||||
// Flatten convert tree map to flat key-value map.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// {"top": {"sub": "value", "sub2": "value2"} }
|
||||
// ->
|
||||
// {"top.sub": "value", "top.sub2": "value2" }
|
||||
func Flatten(mp map[string]any) map[string]any {
|
||||
if mp == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
flatMp := make(map[string]any, len(mp)*2)
|
||||
reflects.FlatMap(reflect.ValueOf(mp), func(path string, val reflect.Value) {
|
||||
flatMp[path] = val.Interface()
|
||||
})
|
||||
|
||||
return flatMp
|
||||
}
|
||||
|
||||
// FlatWithFunc flat a tree-map with custom collect handle func
|
||||
func FlatWithFunc(mp map[string]any, fn reflects.FlatFunc) {
|
||||
if mp == nil || fn == nil {
|
||||
return
|
||||
}
|
||||
reflects.FlatMap(reflect.ValueOf(mp), fn)
|
||||
}
|
||||
Reference in New Issue
Block a user