mirror of
				https://github.com/samber/lo.git
				synced 2025-10-31 19:43:08 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			256 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package lo
 | |
| 
 | |
| import (
 | |
| 	"math/rand"
 | |
| )
 | |
| 
 | |
| // Filter iterates over elements of collection, returning an array of all elements predicate returns truthy for.
 | |
| func Filter[V any](collection []V, predicate func(V, int) bool) []V {
 | |
| 	result := []V{}
 | |
| 
 | |
| 	for i, item := range collection {
 | |
| 		if predicate(item, i) {
 | |
| 			result = append(result, item)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // Map manipulates a slice and transforms it to a slice of another type.
 | |
| func Map[T any, R any](collection []T, iteratee func(T, int) R) []R {
 | |
| 	result := make([]R, len(collection))
 | |
| 
 | |
| 	for i, item := range collection {
 | |
| 		result[i] = iteratee(item, i)
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // FlatMap manipulates a slice and transforms and flattens it to a slice of another type.
 | |
| func FlatMap[T any, R any](collection []T, iteratee func(T, int) []R) []R {
 | |
| 	result := []R{}
 | |
| 
 | |
| 	for i, item := range collection {
 | |
| 		result = append(result, iteratee(item, i)...)
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // Reduce reduces collection to a value which is the accumulated result of running each element in collection
 | |
| // through accumulator, where each successive invocation is supplied the return value of the previous.
 | |
| func Reduce[T any, R any](collection []T, accumulator func(R, T, int) R, initial R) R {
 | |
| 	for i, item := range collection {
 | |
| 		initial = accumulator(initial, item, i)
 | |
| 	}
 | |
| 
 | |
| 	return initial
 | |
| }
 | |
| 
 | |
| // ForEach iterates over elements of collection and invokes iteratee for each element.
 | |
| func ForEach[T any](collection []T, iteratee func(T, int)) {
 | |
| 	for i, item := range collection {
 | |
| 		iteratee(item, i)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Times invokes the iteratee n times, returning an array of the results of each invocation.
 | |
| // The iteratee is invoked with index as argument.
 | |
| func Times[T any](count int, iteratee func(int) T) []T {
 | |
| 	result := make([]T, count)
 | |
| 
 | |
| 	for i := 0; i < count; i++ {
 | |
| 		result[i] = iteratee(i)
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // Uniq returns a duplicate-free version of an array, in which only the first occurrence of each element is kept.
 | |
| // The order of result values is determined by the order they occur in the array.
 | |
| func Uniq[T comparable](collection []T) []T {
 | |
| 	result := make([]T, 0, len(collection))
 | |
| 	seen := make(map[T]struct{}, len(collection))
 | |
| 
 | |
| 	for _, item := range collection {
 | |
| 		if _, ok := seen[item]; ok {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		seen[item] = struct{}{}
 | |
| 		result = append(result, item)
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // Uniq returns a duplicate-free version of an array, in which only the first occurrence of each element is kept.
 | |
| // The order of result values is determined by the order they occur in the array. It accepts `iteratee` which is
 | |
| // invoked for each element in array to generate the criterion by which uniqueness is computed.
 | |
| func UniqBy[T any, U comparable](collection []T, iteratee func(T) U) []T {
 | |
| 	result := make([]T, 0, len(collection))
 | |
| 	seen := make(map[U]struct{}, len(collection))
 | |
| 
 | |
| 	for _, item := range collection {
 | |
| 		key := iteratee(item)
 | |
| 
 | |
| 		if _, ok := seen[key]; ok {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		seen[key] = struct{}{}
 | |
| 		result = append(result, item)
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // GroupBy returns an object composed of keys generated from the results of running each element of collection through iteratee.
 | |
| func GroupBy[T any, U comparable](collection []T, iteratee func(T) U) map[U][]T {
 | |
| 	result := map[U][]T{}
 | |
| 
 | |
| 	for _, item := range collection {
 | |
| 		key := iteratee(item)
 | |
| 
 | |
| 		if _, ok := result[key]; !ok {
 | |
| 			result[key] = []T{}
 | |
| 		}
 | |
| 
 | |
| 		result[key] = append(result[key], item)
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // Chunk returns an array of elements split into groups the length of size. If array can't be split evenly,
 | |
| // the final chunk will be the remaining elements.
 | |
| func Chunk[T any](collection []T, size int) [][]T {
 | |
| 	if size <= 0 {
 | |
| 		panic("Second parameter must be greater than 0")
 | |
| 	}
 | |
| 
 | |
| 	result := make([][]T, 0, len(collection)/2+1)
 | |
| 	length := len(collection)
 | |
| 
 | |
| 	for i := 0; i < length; i++ {
 | |
| 		chunk := i / size
 | |
| 
 | |
| 		if i%size == 0 {
 | |
| 			result = append(result, make([]T, 0, size))
 | |
| 		}
 | |
| 
 | |
| 		result[chunk] = append(result[chunk], collection[i])
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // PartitionBy returns an array of elements split into groups. The order of grouped values is
 | |
| // determined by the order they occur in collection. The grouping is generated from the results
 | |
| // of running each element of collection through iteratee.
 | |
| func PartitionBy[T any, K comparable](collection []T, iteratee func(x T) K) [][]T {
 | |
| 	result := [][]T{}
 | |
| 	seen := map[K]int{}
 | |
| 
 | |
| 	for _, item := range collection {
 | |
| 		key := iteratee(item)
 | |
| 
 | |
| 		resultIndex, ok := seen[key]
 | |
| 		if !ok {
 | |
| 			resultIndex = len(result)
 | |
| 			seen[key] = resultIndex
 | |
| 			result = append(result, []T{})
 | |
| 		}
 | |
| 
 | |
| 		result[resultIndex] = append(result[resultIndex], item)
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| 
 | |
| 	// unordered:
 | |
| 	// groups := GroupBy[T, K](collection, iteratee)
 | |
| 	// return Values[K, []T](groups)
 | |
| }
 | |
| 
 | |
| // Flattens returns an array a single level deep.
 | |
| func Flatten[T any](collection [][]T) []T {
 | |
| 	result := []T{}
 | |
| 
 | |
| 	for _, item := range collection {
 | |
| 		result = append(result, item...)
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // Shuffle returns an array of shuffled values. Uses the Fisher-Yates shuffle algorithm.
 | |
| func Shuffle[T any](collection []T) []T {
 | |
| 	rand.Shuffle(len(collection), func(i, j int) {
 | |
| 		collection[i], collection[j] = collection[j], collection[i]
 | |
| 	})
 | |
| 
 | |
| 	return collection
 | |
| }
 | |
| 
 | |
| // Reverse reverses array so that the first element becomes the last, the second element becomes the second to last, and so on.
 | |
| func Reverse[T any](collection []T) []T {
 | |
| 	length := len(collection)
 | |
| 	half := length / 2
 | |
| 
 | |
| 	for i := 0; i < half; i = i + 1 {
 | |
| 		j := length - 1 - i
 | |
| 		collection[i], collection[j] = collection[j], collection[i]
 | |
| 	}
 | |
| 
 | |
| 	return collection
 | |
| }
 | |
| 
 | |
| // Fill fills elements of array with `initial` value.
 | |
| func Fill[T Clonable[T]](collection []T, initial T) []T {
 | |
| 	result := make([]T, 0, len(collection))
 | |
| 
 | |
| 	for range collection {
 | |
| 		result = append(result, initial.Clone())
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // Repeat builds a slice with N copies of initial value.
 | |
| func Repeat[T Clonable[T]](count int, initial T) []T {
 | |
| 	result := make([]T, 0, count)
 | |
| 
 | |
| 	for i := 0; i < count; i++ {
 | |
| 		result = append(result, initial.Clone())
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // KeyBy transforms a slice or an array of structs to a map based on a pivot callback.
 | |
| func KeyBy[K comparable, V any](collection []V, iteratee func(V) K) map[K]V {
 | |
| 	result := make(map[K]V, len(collection))
 | |
| 
 | |
| 	for _, v := range collection {
 | |
| 		k := iteratee(v)
 | |
| 		result[k] = v
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // Reject is the opposite of Filter, this method returns the elements of collection that predicate does not return truthy for.
 | |
| func Reject[V any](collection []V, predicate func(V, int) bool) []V {
 | |
| 	result := []V{}
 | |
| 
 | |
| 	for i, item := range collection {
 | |
| 		if !predicate(item, i) {
 | |
| 			result = append(result, item)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | 
