You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
267 lines
5.7 KiB
Go
267 lines
5.7 KiB
Go
package narr
|
|
|
|
import (
|
|
"errors"
|
|
"git.noahlan.cn/noahlan/ntool/ndef"
|
|
"git.noahlan.cn/noahlan/ntool/nmath"
|
|
"git.noahlan.cn/noahlan/ntool/nreflect"
|
|
"git.noahlan.cn/noahlan/ntool/nstr"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// 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)
|
|
}
|
|
|
|
// 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(nstr.SafeString(v))
|
|
}
|
|
|
|
return sb.String()
|
|
}
|
|
|
|
/*************************************************************
|
|
* helper func for slices
|
|
*************************************************************/
|
|
|
|
// 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 := nmath.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] = nmath.QuietInt64(v)
|
|
}
|
|
return i64s
|
|
}
|
|
|
|
// StringsAsInts convert and ignore error
|
|
func StringsAsInts(ss []string) []int {
|
|
ints, _ := StringsTryInts(ss)
|
|
return ints
|
|
}
|
|
|
|
// StringsToInts string slice to int slice
|
|
func StringsToInts(ss []string) (ints []int, err error) {
|
|
return StringsTryInts(ss)
|
|
}
|
|
|
|
// StringsTryInts string slice to int slice
|
|
func StringsTryInts(ss []string) (ints []int, err error) {
|
|
for _, str := range ss {
|
|
iVal, err := strconv.Atoi(str)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ints = append(ints, iVal)
|
|
}
|
|
return
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// StringsToSlice convert []string to []any
|
|
func StringsToSlice(ss []string) []any {
|
|
args := make([]any, len(ss))
|
|
for i, s := range ss {
|
|
args[i] = s
|
|
}
|
|
return args
|
|
}
|
|
|
|
// ToStrings convert any(allow: array,slice) to []string
|
|
func ToStrings(arr any) (ret []string, err error) {
|
|
rv := reflect.ValueOf(arr)
|
|
if rv.Kind() == reflect.String {
|
|
return []string{rv.String()}, nil
|
|
}
|
|
|
|
if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array {
|
|
err = ErrInvalidType
|
|
return
|
|
}
|
|
|
|
for i := 0; i < rv.Len(); i++ {
|
|
str, err := nstr.ToString(rv.Index(i).Interface())
|
|
if err != nil {
|
|
return []string{}, err
|
|
}
|
|
|
|
ret = append(ret, str)
|
|
}
|
|
return
|
|
}
|
|
|
|
// SliceToStrings convert []any to []string
|
|
func SliceToStrings(arr []any) []string {
|
|
return QuietStrings(arr)
|
|
}
|
|
|
|
// QuietStrings convert []any to []string
|
|
func QuietStrings(arr []any) []string {
|
|
ss := make([]string, len(arr))
|
|
for i, v := range arr {
|
|
ss[i] = nstr.SafeString(v)
|
|
}
|
|
return ss
|
|
}
|
|
|
|
// ConvType convert type of slice elements to new type slice, by the given newElemTyp type.
|
|
//
|
|
// Supports conversion between []string, []intX, []uintX, []floatX.
|
|
//
|
|
// Usage:
|
|
//
|
|
// ints, _ := narr.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 := nreflect.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 []any to string
|
|
func ToString(arr []any) 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(nstr.SafeString(v))
|
|
}
|
|
|
|
sb.WriteByte(']')
|
|
return sb.String()
|
|
}
|
|
|
|
// CombineToMap combine two slice to map[K]V.
|
|
//
|
|
// If keys length is greater than values, the extra keys will be ignored.
|
|
func CombineToMap[K ndef.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
|
|
}
|