Initial QSfera import
This commit is contained in:
+309
@@ -0,0 +1,309 @@
|
||||
package arrutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/comdef"
|
||||
"github.com/gookit/goutil/mathutil"
|
||||
"github.com/gookit/goutil/reflects"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
// ErrInvalidType error
|
||||
var ErrInvalidType = errors.New("the input param type is invalid")
|
||||
|
||||
/*************************************************************
|
||||
* Join func for slice
|
||||
*************************************************************/
|
||||
|
||||
// JoinStrings alias of strings.Join
|
||||
func JoinStrings(sep string, ss ...string) string {
|
||||
return strings.Join(ss, sep)
|
||||
}
|
||||
|
||||
// StringsJoin alias of strings.Join
|
||||
func StringsJoin(sep string, ss ...string) string {
|
||||
return strings.Join(ss, sep)
|
||||
}
|
||||
|
||||
// JoinTyped join typed []T slice to string.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// JoinTyped(",", 1,2,3) // "1,2,3"
|
||||
// JoinTyped(",", "a","b","c") // "a,b,c"
|
||||
// JoinTyped[any](",", "a",1,"c") // "a,1,c"
|
||||
func JoinTyped[T any](sep string, arr ...T) string {
|
||||
if arr == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
for i, v := range arr {
|
||||
if i > 0 {
|
||||
sb.WriteString(sep)
|
||||
}
|
||||
sb.WriteString(strutil.QuietString(v))
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// JoinSlice join []any slice to string.
|
||||
func JoinSlice(sep string, arr ...any) string {
|
||||
if arr == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
for i, v := range arr {
|
||||
if i > 0 {
|
||||
sb.WriteString(sep)
|
||||
}
|
||||
sb.WriteString(strutil.QuietString(v))
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* convert func for ints
|
||||
*************************************************************/
|
||||
|
||||
// IntsToString convert []T to string
|
||||
func IntsToString[T comdef.Integer](ints []T) string {
|
||||
if len(ints) == 0 {
|
||||
return "[]"
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteByte('[')
|
||||
for i, v := range ints {
|
||||
if i > 0 {
|
||||
sb.WriteByte(',')
|
||||
}
|
||||
sb.WriteString(strconv.FormatInt(int64(v), 10))
|
||||
}
|
||||
sb.WriteByte(']')
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// ToInt64s convert any(allow: array,slice) to []int64
|
||||
func ToInt64s(arr any) (ret []int64, err error) {
|
||||
rv := reflect.ValueOf(arr)
|
||||
if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array {
|
||||
err = ErrInvalidType
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
i64, err := mathutil.Int64(rv.Index(i).Interface())
|
||||
if err != nil {
|
||||
return []int64{}, err
|
||||
}
|
||||
|
||||
ret = append(ret, i64)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MustToInt64s convert any(allow: array,slice) to []int64
|
||||
func MustToInt64s(arr any) []int64 {
|
||||
ret, _ := ToInt64s(arr)
|
||||
return ret
|
||||
}
|
||||
|
||||
// SliceToInt64s convert []any to []int64
|
||||
func SliceToInt64s(arr []any) []int64 {
|
||||
i64s := make([]int64, len(arr))
|
||||
for i, v := range arr {
|
||||
i64s[i] = mathutil.QuietInt64(v)
|
||||
}
|
||||
return i64s
|
||||
}
|
||||
|
||||
// ToMap convert a list to new map.
|
||||
//
|
||||
// Example:
|
||||
// type User struct {
|
||||
// Name string
|
||||
// Age int
|
||||
// }
|
||||
// users := []User{{"Tom", 18}, {"Jack", 20}}
|
||||
// mp := arrutil.ToMap(users, func(u User) (string, int) {
|
||||
// return u.Name, u.Age
|
||||
// })
|
||||
// // mp = map[string]int{"Tom":18, "Jack":20}
|
||||
func ToMap[T any, K comdef.ScalarType, V any](list []T, mapFn func(T) (K, V)) map[K]V {
|
||||
mp := make(map[K]V, len(list))
|
||||
for _, item := range list {
|
||||
k, v := mapFn(item)
|
||||
mp[k] = v
|
||||
}
|
||||
return mp
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* convert func for any-slice
|
||||
*************************************************************/
|
||||
|
||||
// AnyToSlice convert any(allow: array,slice) to []any
|
||||
func AnyToSlice(sl any) (ls []any, err error) {
|
||||
rfKeys := reflect.ValueOf(sl)
|
||||
if rfKeys.Kind() != reflect.Slice && rfKeys.Kind() != reflect.Array {
|
||||
return nil, ErrInvalidType
|
||||
}
|
||||
|
||||
for i := 0; i < rfKeys.Len(); i++ {
|
||||
ls = append(ls, rfKeys.Index(i).Interface())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AnyToStrings convert array or slice to []string
|
||||
func AnyToStrings(arr any) []string {
|
||||
ret, _ := ToStrings(arr)
|
||||
return ret
|
||||
}
|
||||
|
||||
// MustToStrings convert array or slice to []string
|
||||
func MustToStrings(arr any) []string {
|
||||
ret, err := ToStrings(arr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ToStrings convert any(allow: array,slice) to []string
|
||||
func ToStrings(arr any) (ret []string, err error) {
|
||||
// try direct convert
|
||||
switch typVal := arr.(type) {
|
||||
case string:
|
||||
return []string{typVal}, nil
|
||||
case []string:
|
||||
return typVal, nil
|
||||
case []any:
|
||||
return SliceToStrings(typVal), nil
|
||||
}
|
||||
|
||||
// try use reflect to convert
|
||||
rv := reflect.ValueOf(arr)
|
||||
if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array {
|
||||
err = ErrInvalidType
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
str, err1 := strutil.ToString(rv.Index(i).Interface())
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
}
|
||||
ret = append(ret, str)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SliceToStrings safe convert []any to []string
|
||||
func SliceToStrings(arr []any) []string {
|
||||
ss := make([]string, len(arr))
|
||||
for i, v := range arr {
|
||||
ss[i] = strutil.SafeString(v)
|
||||
}
|
||||
return ss
|
||||
}
|
||||
|
||||
// QuietStrings safe convert []any to []string
|
||||
func QuietStrings(arr []any) []string { return SliceToStrings(arr) }
|
||||
|
||||
// ConvType convert type of slice elements to new type slice, by the given newElemTyp type.
|
||||
//
|
||||
// Supports conversion between []string, []intX, []uintX, []floatX.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// ints, _ := arrutil.ConvType([]string{"12", "23"}, 1) // []int{12, 23}
|
||||
func ConvType[T any, R any](arr []T, newElemTyp R) ([]R, error) {
|
||||
newArr := make([]R, len(arr))
|
||||
elemTyp := reflect.TypeOf(newElemTyp)
|
||||
|
||||
for i, elem := range arr {
|
||||
var anyElem any = elem
|
||||
// type is same.
|
||||
if _, ok := anyElem.(R); ok {
|
||||
newArr[i] = anyElem.(R)
|
||||
continue
|
||||
}
|
||||
|
||||
// need conv type.
|
||||
rfVal, err := reflects.ValueByType(elem, elemTyp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newArr[i] = rfVal.Interface().(R)
|
||||
}
|
||||
return newArr, nil
|
||||
}
|
||||
|
||||
// AnyToString simple and quickly convert any array, slice to string
|
||||
func AnyToString(arr any) string {
|
||||
return NewFormatter(arr).Format()
|
||||
}
|
||||
|
||||
// SliceToString convert []any to string
|
||||
func SliceToString(arr ...any) string { return ToString(arr) }
|
||||
|
||||
// ToString simple and quickly convert []T to string
|
||||
func ToString[T any](arr []T) string {
|
||||
// like fmt.Println([]any(nil))
|
||||
if arr == nil {
|
||||
return "[]"
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteByte('[')
|
||||
|
||||
for i, v := range arr {
|
||||
if i > 0 {
|
||||
sb.WriteByte(',')
|
||||
}
|
||||
sb.WriteString(strutil.SafeString(v))
|
||||
}
|
||||
|
||||
sb.WriteByte(']')
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// CombineToMap combine []K and []V slice to map[K]V.
|
||||
//
|
||||
// If keys length is greater than values, the extra keys will be ignored.
|
||||
func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V {
|
||||
ln := len(values)
|
||||
mp := make(map[K]V, len(keys))
|
||||
|
||||
for i, key := range keys {
|
||||
if i >= ln {
|
||||
break
|
||||
}
|
||||
mp[key] = values[i]
|
||||
}
|
||||
return mp
|
||||
}
|
||||
|
||||
// CombineToSMap combine two string-slice to map[string]string
|
||||
func CombineToSMap(keys, values []string) map[string]string {
|
||||
ln := len(values)
|
||||
mp := make(map[string]string, len(keys))
|
||||
|
||||
for i, key := range keys {
|
||||
if ln > i {
|
||||
mp[key] = values[i]
|
||||
} else {
|
||||
mp[key] = ""
|
||||
}
|
||||
}
|
||||
return mp
|
||||
}
|
||||
Reference in New Issue
Block a user