utils/util.go (352 lines of code) (raw):
package utils
import (
"encoding/json"
"fmt"
"strings"
"time"
"github.com/aliyun/aliyun-pairec-config-go-sdk/v2/model"
"github.com/tidwall/gjson"
)
func CostTime(start time.Time) int64 {
duration := time.Now().UnixNano() - start.UnixNano()
return duration / 1e6
}
type FeatureInfo struct {
Value interface{} `json:"value"`
Type string `json:"type"`
}
func ConvertFeatures(features map[string]interface{}) map[string]*FeatureInfo {
ret := make(map[string]*FeatureInfo, len(features))
for name, value := range features {
info := &FeatureInfo{
Value: value,
Type: GetTypeOf(value),
}
ret[name] = info
}
return ret
}
func GetTypeOf(value interface{}) string {
switch value.(type) {
case int:
return "int"
case int32:
return "int"
case int64:
return "bigint"
case string:
return "string"
case float64:
return "float64"
case bool:
return "bool"
case []int:
return "list<int>"
case []int32:
return "list<int>"
case []int64:
return "list<int64>"
case []float32:
return "list<float>"
case []float64:
return "list<double>"
case []string:
return "list<string>"
case [][]float32:
return "list<list<float>>"
case [][]float64:
return "list<list<double>>"
case map[string]string:
return "map<string,string>"
case map[string]int:
return "map<string,int>"
case map[string]int32:
return "map<string,int>"
case map[string]int64:
return "map<string,int64>"
case map[string]float32:
return "map<string,float>"
case map[string]float64:
return "map<string,double>"
case map[int]int:
return "map<int,int>"
case map[int]int32:
return "map<int,int>"
case map[int32]int32:
return "map<int,int>"
case map[int]int64:
return "map<int,int64>"
case map[int]float32:
return "map<int,float>"
case map[int]float64:
return "map<int,double>"
case map[int]string:
return "map<int,string>"
case map[int64]int64:
return "map<int64,int64>"
case map[int64]int:
return "map<int64,int>"
case map[int64]int32:
return "map<int64,int>"
case map[int64]float32:
return "map<int64,float>"
case map[int64]float64:
return "map<int64,double>"
case map[int64]string:
return "map<int64,string>"
default:
fmt.Printf("ConvertFeatures not find tyep info, value:%v, type:%T\n", value, value)
return "none"
}
}
func GetValueByType(value interface{}, vtype string) interface{} {
switch vtype {
case "int":
return ToInt(value, 0)
case "string":
return ToString(value, "")
case "float64":
return ToFloat(value, float64(0))
case "int64":
return ToInt64(value, 0)
case "bigint":
return ToInt64(value, 0)
case "bool":
return ToBool(value, false)
case "list<string>":
return ToStringArray(value)
case "list<int>":
return ToIntArray(value)
case "list<int64>":
if vals, ok := value.([]any); ok {
values := make([]int64, 0, len(vals))
for _, v := range vals {
values = append(values, ToInt64(v, 0))
}
return values
}
case "list<double>":
if vals, ok := value.([]any); ok {
values := make([]float64, 0, len(vals))
for _, v := range vals {
values = append(values, ToFloat(v, 0))
}
return values
}
case "list<float>":
if vals, ok := value.([]any); ok {
values := make([]float32, 0, len(vals))
for _, v := range vals {
values = append(values, ToFloat32(v, 0))
}
return values
}
case "list<list<float>>":
if vals, ok := value.([]any); ok {
values := make([][]float32, 0, len(vals))
for _, vlist := range vals {
if lists, ok := vlist.([]any); ok {
list := make([]float32, 0, len(lists))
for _, v := range lists {
list = append(list, ToFloat32(v, 0))
}
values = append(values, list)
}
}
return values
}
case "list<list<double>>":
if vals, ok := value.([]any); ok {
values := make([][]float64, 0, len(vals))
for _, vlist := range vals {
if lists, ok := vlist.([]any); ok {
list := make([]float64, 0, len(lists))
for _, v := range lists {
list = append(list, ToFloat(v, 0))
}
values = append(values, list)
}
}
return values
}
case "map<string,string>":
if vals, ok := value.(map[string]any); ok {
values := make(map[string]string, len(vals))
for k, v := range vals {
values[k] = ToString(v, "")
}
return values
}
case "map<string,int>":
if vals, ok := value.(map[string]any); ok {
values := make(map[string]int, len(vals))
for k, v := range vals {
values[k] = ToInt(v, 0)
}
return values
}
case "map<string,int64>":
if vals, ok := value.(map[string]any); ok {
values := make(map[string]int64, len(vals))
for k, v := range vals {
values[k] = ToInt64(v, 0)
}
return values
}
case "map<string,float>":
if vals, ok := value.(map[string]any); ok {
values := make(map[string]float32, len(vals))
for k, v := range vals {
values[k] = ToFloat32(v, 0)
}
return values
}
case "map<string,double>":
if vals, ok := value.(map[string]any); ok {
values := make(map[string]float64, len(vals))
for k, v := range vals {
values[k] = ToFloat(v, 0)
}
return values
}
case "map<int,int>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int]int, len(vals))
for k, v := range vals {
values[ToInt(k, 0)] = ToInt(v, 0)
}
return values
}
case "map<int,int64>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int]int64, len(vals))
for k, v := range vals {
values[ToInt(k, 0)] = ToInt64(v, 0)
}
return values
}
case "map<int,double>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int]float64, len(vals))
for k, v := range vals {
values[ToInt(k, 0)] = ToFloat(v, 0)
}
return values
}
case "map<int,float>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int]float32, len(vals))
for k, v := range vals {
values[ToInt(k, 0)] = ToFloat32(v, 0)
}
return values
}
case "map<int,string>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int]string, len(vals))
for k, v := range vals {
values[ToInt(k, 0)] = ToString(v, "")
}
return values
}
case "map<int64,int>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int64]int, len(vals))
for k, v := range vals {
values[ToInt64(k, 0)] = ToInt(v, 0)
}
return values
}
case "map<int64,int64>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int64]int64, len(vals))
for k, v := range vals {
values[ToInt64(k, 0)] = ToInt64(v, 0)
}
return values
}
case "map<int64,double>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int64]float64, len(vals))
for k, v := range vals {
values[ToInt64(k, 0)] = ToFloat(v, 0)
}
return values
}
case "map<int64,float>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int64]float32, len(vals))
for k, v := range vals {
values[ToInt64(k, 0)] = ToFloat32(v, 0)
}
return values
}
case "map<int64,string>":
if vals, ok := value.(map[string]any); ok {
values := make(map[int64]string, len(vals))
for k, v := range vals {
values[ToInt64(k, 0)] = ToString(v, "")
}
return values
}
default:
return value
}
return value
}
func IndexOf(a []string, e string) int {
n := len(a)
var i = 0
for ; i < n; i++ {
if e == a[i] {
return i
}
}
return -1
}
func UniqueStrings(strSlice []string) []string {
keys := make(map[string]bool)
list := make([]string, 0, len(strSlice))
for _, entry := range strSlice {
if _, ok := keys[entry]; !ok {
keys[entry] = true
list = append(list, entry)
}
}
return list
}
func GetExperimentParamByPath(params model.LayerParams, path string, defaultValue interface{}) interface{} {
if strings.Contains(path, ".") {
pos := strings.Index(path, ".")
root := path[:pos]
rootConf := params.Get(root, nil)
if rootConf == nil {
return defaultValue
}
newPath := path[pos+1:]
if newPath == "" {
return rootConf
}
if dict, ok := rootConf.(map[string]interface{}); ok {
b, err := json.Marshal(dict)
if err != nil {
fmt.Sprintf("GetExpParamByPath Marshal fail: %v", err)
return defaultValue
}
value := gjson.Get(string(b), newPath).Value()
if value == nil {
return defaultValue
}
return value
} else if feature, okay := rootConf.(string); okay {
value := gjson.Get(feature, newPath).Value()
if value == nil {
return defaultValue
}
return value
} else {
return defaultValue
}
}
return params.Get(path, defaultValue)
}