github.com/kyleu/dbaudit@v0.0.2-0.20240321155047-ff2f2c940496/app/util/array.go (about)

     1  // Package util - Content managed by Project Forge, see [projectforge.md] for details.
     2  package util
     3  
     4  import (
     5  	"cmp"
     6  	"fmt"
     7  	"reflect"
     8  	"slices"
     9  
    10  	"github.com/pkg/errors"
    11  	"github.com/samber/lo"
    12  )
    13  
    14  func StringArrayMaxLength(a []string) int {
    15  	return len(lo.MaxBy(a, func(x string, max string) bool {
    16  		return len(x) > len(max)
    17  	}))
    18  }
    19  
    20  func ArrayToStringArray[T any](a []T) []string {
    21  	return lo.Map(a, func(x T, _ int) string {
    22  		return fmt.Sprint(x)
    23  	})
    24  }
    25  
    26  func StringArrayQuoted(a []string) []string {
    27  	return lo.Map(a, func(x string, _ int) string {
    28  		return fmt.Sprintf("%q", x)
    29  	})
    30  }
    31  
    32  func StringArrayFromAny(a []any, maxLength int) []string {
    33  	ret := NewStringSlice(make([]string, 0, len(a)))
    34  	lo.ForEach(a, func(x any, _ int) {
    35  		var v string
    36  		switch t := x.(type) {
    37  		case string:
    38  			v = t
    39  		case []byte:
    40  			v = string(t)
    41  		default:
    42  			v = fmt.Sprint(x)
    43  		}
    44  		if maxLength > 0 && len(v) > maxLength {
    45  			v = v[:maxLength] + "... (truncated)"
    46  		}
    47  		ret.Push(v)
    48  	})
    49  	return ret.Slice
    50  }
    51  
    52  func ArrayRemoveDuplicates[T comparable](x []T) []T {
    53  	return lo.Uniq(x)
    54  }
    55  
    56  func ArraySorted[T cmp.Ordered](x []T) []T {
    57  	slices.Sort(x)
    58  	return x
    59  }
    60  
    61  func StringArrayOxfordComma(names []string, separator string) string {
    62  	ret := ""
    63  	lo.ForEach(names, func(name string, idx int) {
    64  		if idx > 0 {
    65  			if idx == (len(names) - 1) {
    66  				if idx > 1 {
    67  					ret += ","
    68  				}
    69  				ret += " " + separator + " "
    70  			} else {
    71  				ret += ", "
    72  			}
    73  		}
    74  		ret += name
    75  	})
    76  	return ret
    77  }
    78  
    79  func ArrayTransform[T any, U any](x []T, f func(T) U) []U {
    80  	return lo.Map(x, func(i T, _ int) U {
    81  		return f(i)
    82  	})
    83  }
    84  
    85  func ArrayRemoveNil[T any](x []*T) []*T {
    86  	return lo.Reject(x, func(el *T, _ int) bool {
    87  		return el == nil
    88  	})
    89  }
    90  
    91  func ArrayDereference[T any](x []*T) []T {
    92  	return lo.Map(x, func(el *T, _ int) T {
    93  		return lo.FromPtr(el)
    94  	})
    95  }
    96  
    97  func LengthAny(dest any) int {
    98  	defer func() { _ = recover() }()
    99  	rfl := reflect.ValueOf(dest)
   100  	if rfl.Kind() == reflect.Ptr {
   101  		rfl = rfl.Elem()
   102  	}
   103  	return rfl.Len()
   104  }
   105  
   106  func ArrayFromAny(dest any) []any {
   107  	defer func() { _ = recover() }()
   108  	rfl := reflect.ValueOf(dest)
   109  	if rfl.Kind() == reflect.Ptr {
   110  		rfl = rfl.Elem()
   111  	}
   112  	if k := rfl.Kind(); k == reflect.Array || k == reflect.Slice {
   113  		return lo.Times(rfl.Len(), func(i int) any {
   114  			return rfl.Index(i).Interface()
   115  		})
   116  	}
   117  	return []any{dest}
   118  }
   119  
   120  func ArrayFlatten[T any](arrs ...[]T) []T {
   121  	return lo.Flatten(arrs)
   122  }
   123  
   124  func ArrayFirstN[V any](items []V, n int) []V {
   125  	if n > len(items) {
   126  		return items
   127  	}
   128  	return items[:n]
   129  }
   130  
   131  func ArrayLastN[V any](items []V, n int) []V {
   132  	if n > len(items) {
   133  		return items
   134  	}
   135  	return items[len(items)-n:]
   136  }
   137  
   138  func MapError[T any, U any](xa []T, f func(el T, idx int) (U, error)) ([]U, error) {
   139  	ret := make([]U, 0, len(xa))
   140  	for i, x := range xa {
   141  		candidate, err := f(x, i)
   142  		if err != nil {
   143  			return nil, errors.Wrapf(err, "error processing element [%d]", i)
   144  		}
   145  		ret = append(ret, candidate)
   146  	}
   147  	return ret, nil
   148  }