github.com/clubpay/ronykit/kit@v0.14.4-0.20240515065620-d0dace45cbc7/utils/array.go (about)

     1  package utils
     2  
     3  // Filter returns a new slice containing only the elements in tt for which the match function returns true.
     4  //
     5  //		type User struct {
     6  //			Name string
     7  //			Age  int
     8  //			Active bool
     9  //	}
    10  //
    11  //	var users = []User{
    12  //		{"Tom", 20, true},
    13  //		{"Jack", 22, false},
    14  //		{"Mary", 18, true},
    15  //	}
    16  //
    17  //	var activeUsers = qkit.Filter(func(u User) bool {
    18  //		return u.Active
    19  //	}, users)
    20  //
    21  // fmt.Println(activeUsers)
    22  //
    23  // Playground: https://go.dev/play/p/70YOKRs79OF
    24  func Filter[T any](match func(src T) bool, tt []T) []T {
    25  	ftt := make([]T, 0, len(tt))
    26  	for _, t := range tt {
    27  		if match(t) {
    28  			ftt = append(ftt, t)
    29  		}
    30  	}
    31  
    32  	return ftt[:len(ftt):len(ftt)]
    33  }
    34  
    35  // Map applies the transformer function to each element of the slice ss.
    36  // The result is a slice of the same length as ss, where the kth element is transformer(ss[k]).
    37  //
    38  //	type User struct {
    39  //		Name string
    40  //		Age  int
    41  //	}
    42  //
    43  //	var users = []User{
    44  //		{"Tom", 20},
    45  //		{"Jack", 22},
    46  //		{"Mary", 18},
    47  //	}
    48  //
    49  //	var names = qkit.Map(func(u User) string {
    50  //		return u.Name
    51  //	}, users)
    52  //
    53  // fmt.Println(names)
    54  //
    55  // Playground: https://go.dev/play/p/wKIa32-rMDn
    56  func Map[S, D any](transformer func(src S) D, ss []S) []D {
    57  	dd := make([]D, len(ss))
    58  	for k, src := range ss {
    59  		dd[k] = transformer(src)
    60  	}
    61  
    62  	return dd
    63  }
    64  
    65  // Reduce [T, R] reduces the slice tt to a single value r using the reducer
    66  // function. The reducer function takes the current reduced value r and the
    67  // current slice value t and returns a new reduced value.
    68  //
    69  //	type User struct {
    70  //		Name string
    71  //		Age  int
    72  //	}
    73  //
    74  //	var users = []User{
    75  //		{"Tom", 20},
    76  //		{"Jack", 22},
    77  //		{"Mary", 18},
    78  //	}
    79  //
    80  //	var totalAge = qkit.Reduce(func(r int, u User) int {
    81  //		return r + u.Age
    82  //	}, users)
    83  //
    84  // fmt.Println(totalAge)
    85  //
    86  // Playground: https://go.dev/play/p/gf9evzMIMIK
    87  func Reduce[T, R any](reducer func(r R, t T) R, tt []T) R {
    88  	var r R
    89  	for _, t := range tt {
    90  		r = reducer(r, t)
    91  	}
    92  
    93  	return r
    94  }
    95  
    96  // Paginate will call the given function with start and end indexes
    97  // for a slice of the given size.
    98  //
    99  //	type User struct {
   100  //		Name string
   101  //		Age  int
   102  //	}
   103  //
   104  //	var users = []User{
   105  //		{"Tom", 20},
   106  //		{"Jack", 22},
   107  //		{"Mary", 18},
   108  //		{"Tommy", 20},
   109  //		{"Lin", 22},
   110  //	}
   111  //
   112  //	qkit.Paginate(users, 2, func(start, end int) error {
   113  //		fmt.Println(users[start:end])
   114  //		return nil
   115  //	})
   116  //
   117  // Playground: https://go.dev/play/p/aDiVJEKjgwW
   118  func Paginate[T any](arr []T, pageSize int, fn func(start, end int) error) error {
   119  	start := 0
   120  	for {
   121  		end := start + pageSize
   122  		if end > len(arr) {
   123  			end = len(arr)
   124  		}
   125  		err := fn(start, end)
   126  		if err != nil {
   127  			return err
   128  		}
   129  		start = end
   130  		if start >= len(arr) {
   131  			break
   132  		}
   133  	}
   134  
   135  	return nil
   136  }
   137  
   138  // MapToArray converts a map's values to a slice.
   139  func MapToArray[K comparable, V any](s map[K]V) []V {
   140  	arr := make([]V, 0, len(s))
   141  	for _, v := range s {
   142  		arr = append(arr, v)
   143  	}
   144  
   145  	return arr
   146  }
   147  
   148  // MapKeysToArray converts a map's keys to a slice.
   149  func MapKeysToArray[K comparable, V any](s map[K]V) []K {
   150  	arr := make([]K, 0, len(s))
   151  	for k := range s {
   152  		arr = append(arr, k)
   153  	}
   154  
   155  	return arr
   156  }
   157  
   158  // ArrayToMap converts a slice to a map with the index as the key.
   159  func ArrayToMap[V any](s []V) map[int]V {
   160  	m := make(map[int]V, len(s))
   161  	for idx, v := range s {
   162  		m[idx] = v
   163  	}
   164  
   165  	return m
   166  }
   167  
   168  func ArrayToSet[T comparable](s []T) map[T]struct{} {
   169  	m := make(map[T]struct{}, len(s))
   170  	for _, v := range s {
   171  		m[v] = struct{}{}
   172  	}
   173  
   174  	return m
   175  }
   176  
   177  func Contains[T comparable](s []T, v T) bool {
   178  	for _, vv := range s {
   179  		if vv == v {
   180  			return true
   181  		}
   182  	}
   183  
   184  	return false
   185  }
   186  
   187  func ContainsAny[T comparable](s []T, v []T) bool {
   188  	for _, vv := range v {
   189  		if Contains(s, vv) {
   190  			return true
   191  		}
   192  	}
   193  
   194  	return false
   195  }
   196  
   197  func ContainsAll[T comparable](s []T, v []T) bool {
   198  	for _, vv := range v {
   199  		if !Contains(s, vv) {
   200  			return false
   201  		}
   202  	}
   203  
   204  	return true
   205  }
   206  
   207  // First returns the first value found in the map for the given keys.
   208  func First[K, V comparable](in map[K]V, keys ...K) (V, bool) {
   209  	var zero V
   210  	for _, k := range keys {
   211  		if v, ok := in[k]; ok {
   212  			return v, true
   213  		}
   214  	}
   215  
   216  	return zero, false
   217  }
   218  
   219  func FirstOr[K, V comparable](def V, in map[K]V, keys ...K) V {
   220  	v, ok := First(in, keys...)
   221  	if ok {
   222  		return v
   223  	}
   224  
   225  	return def
   226  }
   227  
   228  func ForEach[V any](in []V, fn func(*V)) {
   229  	for idx := range in {
   230  		fn(&in[idx])
   231  	}
   232  }
   233  
   234  func AddUnique[T comparable](s []T, v T) []T {
   235  	if Contains(s, v) {
   236  		return s
   237  	}
   238  
   239  	return append(s, v)
   240  }