diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-22 17:35:49 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-22 17:35:49 -0600 |
| commit | 20ef0d92694465ac86b550df139e8366a0a2b4fa (patch) | |
| tree | 3f14589e1ce6eb9306a3af31c3a1f9e1af5ed637 /vendor/github.com/samber/lo/find.go | |
| parent | 44e0d272c040cdc53a98b9f1dc58ae7da67752e6 (diff) | |
feat: connect to spicedb
Diffstat (limited to 'vendor/github.com/samber/lo/find.go')
| -rw-r--r-- | vendor/github.com/samber/lo/find.go | 651 |
1 files changed, 651 insertions, 0 deletions
diff --git a/vendor/github.com/samber/lo/find.go b/vendor/github.com/samber/lo/find.go new file mode 100644 index 0000000..f04dc08 --- /dev/null +++ b/vendor/github.com/samber/lo/find.go @@ -0,0 +1,651 @@ +package lo + +import ( + "fmt" + "time" + + "github.com/samber/lo/internal/constraints" + "github.com/samber/lo/internal/rand" +) + +// IndexOf returns the index at which the first occurrence of a value is found in an array or return -1 +// if the value cannot be found. +func IndexOf[T comparable](collection []T, element T) int { + for i := range collection { + if collection[i] == element { + return i + } + } + + return -1 +} + +// LastIndexOf returns the index at which the last occurrence of a value is found in an array or return -1 +// if the value cannot be found. +func LastIndexOf[T comparable](collection []T, element T) int { + length := len(collection) + + for i := length - 1; i >= 0; i-- { + if collection[i] == element { + return i + } + } + + return -1 +} + +// Find search an element in a slice based on a predicate. It returns element and true if element was found. +func Find[T any](collection []T, predicate func(item T) bool) (T, bool) { + for i := range collection { + if predicate(collection[i]) { + return collection[i], true + } + } + + var result T + return result, false +} + +// FindIndexOf searches an element in a slice based on a predicate and returns the index and true. +// It returns -1 and false if the element is not found. +func FindIndexOf[T any](collection []T, predicate func(item T) bool) (T, int, bool) { + for i := range collection { + if predicate(collection[i]) { + return collection[i], i, true + } + } + + var result T + return result, -1, false +} + +// FindLastIndexOf searches last element in a slice based on a predicate and returns the index and true. +// It returns -1 and false if the element is not found. +func FindLastIndexOf[T any](collection []T, predicate func(item T) bool) (T, int, bool) { + length := len(collection) + + for i := length - 1; i >= 0; i-- { + if predicate(collection[i]) { + return collection[i], i, true + } + } + + var result T + return result, -1, false +} + +// FindOrElse search an element in a slice based on a predicate. It returns the element if found or a given fallback value otherwise. +func FindOrElse[T any](collection []T, fallback T, predicate func(item T) bool) T { + for i := range collection { + if predicate(collection[i]) { + return collection[i] + } + } + + return fallback +} + +// FindKey returns the key of the first value matching. +func FindKey[K comparable, V comparable](object map[K]V, value V) (K, bool) { + for k := range object { + if object[k] == value { + return k, true + } + } + + return Empty[K](), false +} + +// FindKeyBy returns the key of the first element predicate returns truthy for. +func FindKeyBy[K comparable, V any](object map[K]V, predicate func(key K, value V) bool) (K, bool) { + for k := range object { + if predicate(k, object[k]) { + return k, true + } + } + + return Empty[K](), false +} + +// FindUniques returns a slice with all the unique elements of the collection. +// The order of result values is determined by the order they occur in the collection. +func FindUniques[T comparable, Slice ~[]T](collection Slice) Slice { + isDupl := make(map[T]bool, len(collection)) + + for i := range collection { + duplicated, ok := isDupl[collection[i]] + if !ok { + isDupl[collection[i]] = false + } else if !duplicated { + isDupl[collection[i]] = true + } + } + + result := make(Slice, 0, len(collection)-len(isDupl)) + + for i := range collection { + if duplicated := isDupl[collection[i]]; !duplicated { + result = append(result, collection[i]) + } + } + + return result +} + +// FindUniquesBy returns a slice with all the unique elements of the collection. +// 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 FindUniquesBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) Slice { + isDupl := make(map[U]bool, len(collection)) + + for i := range collection { + key := iteratee(collection[i]) + + duplicated, ok := isDupl[key] + if !ok { + isDupl[key] = false + } else if !duplicated { + isDupl[key] = true + } + } + + result := make(Slice, 0, len(collection)-len(isDupl)) + + for i := range collection { + key := iteratee(collection[i]) + + if duplicated := isDupl[key]; !duplicated { + result = append(result, collection[i]) + } + } + + return result +} + +// FindDuplicates returns a slice with the first occurrence of each duplicated elements of the collection. +// The order of result values is determined by the order they occur in the collection. +func FindDuplicates[T comparable, Slice ~[]T](collection Slice) Slice { + isDupl := make(map[T]bool, len(collection)) + + for i := range collection { + duplicated, ok := isDupl[collection[i]] + if !ok { + isDupl[collection[i]] = false + } else if !duplicated { + isDupl[collection[i]] = true + } + } + + result := make(Slice, 0, len(collection)-len(isDupl)) + + for i := range collection { + if duplicated := isDupl[collection[i]]; duplicated { + result = append(result, collection[i]) + isDupl[collection[i]] = false + } + } + + return result +} + +// FindDuplicatesBy returns a slice with the first occurrence of each duplicated elements of the collection. +// 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 FindDuplicatesBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) Slice { + isDupl := make(map[U]bool, len(collection)) + + for i := range collection { + key := iteratee(collection[i]) + + duplicated, ok := isDupl[key] + if !ok { + isDupl[key] = false + } else if !duplicated { + isDupl[key] = true + } + } + + result := make(Slice, 0, len(collection)-len(isDupl)) + + for i := range collection { + key := iteratee(collection[i]) + + if duplicated := isDupl[key]; duplicated { + result = append(result, collection[i]) + isDupl[key] = false + } + } + + return result +} + +// Min search the minimum value of a collection. +// Returns zero value when the collection is empty. +func Min[T constraints.Ordered](collection []T) T { + var min T + + if len(collection) == 0 { + return min + } + + min = collection[0] + + for i := 1; i < len(collection); i++ { + item := collection[i] + + if item < min { + min = item + } + } + + return min +} + +// MinIndex search the minimum value of a collection and the index of the minimum value. +// Returns (zero value, -1) when the collection is empty. +func MinIndex[T constraints.Ordered](collection []T) (T, int) { + var ( + min T + index int + ) + + if len(collection) == 0 { + return min, -1 + } + + min = collection[0] + + for i := 1; i < len(collection); i++ { + item := collection[i] + + if item < min { + min = item + index = i + } + } + + return min, index +} + +// MinBy search the minimum value of a collection using the given comparison function. +// If several values of the collection are equal to the smallest value, returns the first such value. +// Returns zero value when the collection is empty. +func MinBy[T any](collection []T, comparison func(a T, b T) bool) T { + var min T + + if len(collection) == 0 { + return min + } + + min = collection[0] + + for i := 1; i < len(collection); i++ { + item := collection[i] + + if comparison(item, min) { + min = item + } + } + + return min +} + +// MinIndexBy search the minimum value of a collection using the given comparison function and the index of the minimum value. +// If several values of the collection are equal to the smallest value, returns the first such value. +// Returns (zero value, -1) when the collection is empty. +func MinIndexBy[T any](collection []T, comparison func(a T, b T) bool) (T, int) { + var ( + min T + index int + ) + + if len(collection) == 0 { + return min, -1 + } + + min = collection[0] + + for i := 1; i < len(collection); i++ { + item := collection[i] + + if comparison(item, min) { + min = item + index = i + } + } + + return min, index +} + +// Earliest search the minimum time.Time of a collection. +// Returns zero value when the collection is empty. +func Earliest(times ...time.Time) time.Time { + var min time.Time + + if len(times) == 0 { + return min + } + + min = times[0] + + for i := 1; i < len(times); i++ { + item := times[i] + + if item.Before(min) { + min = item + } + } + + return min +} + +// EarliestBy search the minimum time.Time of a collection using the given iteratee function. +// Returns zero value when the collection is empty. +func EarliestBy[T any](collection []T, iteratee func(item T) time.Time) T { + var earliest T + + if len(collection) == 0 { + return earliest + } + + earliest = collection[0] + earliestTime := iteratee(collection[0]) + + for i := 1; i < len(collection); i++ { + itemTime := iteratee(collection[i]) + + if itemTime.Before(earliestTime) { + earliest = collection[i] + earliestTime = itemTime + } + } + + return earliest +} + +// Max searches the maximum value of a collection. +// Returns zero value when the collection is empty. +func Max[T constraints.Ordered](collection []T) T { + var max T + + if len(collection) == 0 { + return max + } + + max = collection[0] + + for i := 1; i < len(collection); i++ { + item := collection[i] + + if item > max { + max = item + } + } + + return max +} + +// MaxIndex searches the maximum value of a collection and the index of the maximum value. +// Returns (zero value, -1) when the collection is empty. +func MaxIndex[T constraints.Ordered](collection []T) (T, int) { + var ( + max T + index int + ) + + if len(collection) == 0 { + return max, -1 + } + + max = collection[0] + + for i := 1; i < len(collection); i++ { + item := collection[i] + + if item > max { + max = item + index = i + } + } + + return max, index +} + +// MaxBy search the maximum value of a collection using the given comparison function. +// If several values of the collection are equal to the greatest value, returns the first such value. +// Returns zero value when the collection is empty. +func MaxBy[T any](collection []T, comparison func(a T, b T) bool) T { + var max T + + if len(collection) == 0 { + return max + } + + max = collection[0] + + for i := 1; i < len(collection); i++ { + item := collection[i] + + if comparison(item, max) { + max = item + } + } + + return max +} + +// MaxIndexBy search the maximum value of a collection using the given comparison function and the index of the maximum value. +// If several values of the collection are equal to the greatest value, returns the first such value. +// Returns (zero value, -1) when the collection is empty. +func MaxIndexBy[T any](collection []T, comparison func(a T, b T) bool) (T, int) { + var ( + max T + index int + ) + + if len(collection) == 0 { + return max, -1 + } + + max = collection[0] + + for i := 1; i < len(collection); i++ { + item := collection[i] + + if comparison(item, max) { + max = item + index = i + } + } + + return max, index +} + +// Latest search the maximum time.Time of a collection. +// Returns zero value when the collection is empty. +func Latest(times ...time.Time) time.Time { + var max time.Time + + if len(times) == 0 { + return max + } + + max = times[0] + + for i := 1; i < len(times); i++ { + item := times[i] + + if item.After(max) { + max = item + } + } + + return max +} + +// LatestBy search the maximum time.Time of a collection using the given iteratee function. +// Returns zero value when the collection is empty. +func LatestBy[T any](collection []T, iteratee func(item T) time.Time) T { + var latest T + + if len(collection) == 0 { + return latest + } + + latest = collection[0] + latestTime := iteratee(collection[0]) + + for i := 1; i < len(collection); i++ { + itemTime := iteratee(collection[i]) + + if itemTime.After(latestTime) { + latest = collection[i] + latestTime = itemTime + } + } + + return latest +} + +// First returns the first element of a collection and check for availability of the first element. +func First[T any](collection []T) (T, bool) { + length := len(collection) + + if length == 0 { + var t T + return t, false + } + + return collection[0], true +} + +// FirstOrEmpty returns the first element of a collection or zero value if empty. +func FirstOrEmpty[T any](collection []T) T { + i, _ := First(collection) + return i +} + +// FirstOr returns the first element of a collection or the fallback value if empty. +func FirstOr[T any](collection []T, fallback T) T { + i, ok := First(collection) + if !ok { + return fallback + } + + return i +} + +// Last returns the last element of a collection or error if empty. +func Last[T any](collection []T) (T, bool) { + length := len(collection) + + if length == 0 { + var t T + return t, false + } + + return collection[length-1], true +} + +// LastOrEmpty returns the last element of a collection or zero value if empty. +func LastOrEmpty[T any](collection []T) T { + i, _ := Last(collection) + return i +} + +// LastOr returns the last element of a collection or the fallback value if empty. +func LastOr[T any](collection []T, fallback T) T { + i, ok := Last(collection) + if !ok { + return fallback + } + + return i +} + +// Nth returns the element at index `nth` of collection. If `nth` is negative, the nth element +// from the end is returned. An error is returned when nth is out of slice bounds. +func Nth[T any, N constraints.Integer](collection []T, nth N) (T, error) { + n := int(nth) + l := len(collection) + if n >= l || -n > l { + var t T + return t, fmt.Errorf("nth: %d out of slice bounds", n) + } + + if n >= 0 { + return collection[n], nil + } + return collection[l+n], nil +} + +// NthOr returns the element at index `nth` of collection. +// If `nth` is negative, it returns the nth element from the end. +// If `nth` is out of slice bounds, it returns the fallback value instead of an error. +func NthOr[T any, N constraints.Integer](collection []T, nth N, fallback T) T { + value, err := Nth(collection, nth) + if err != nil { + return fallback + } + return value +} + +// NthOrEmpty returns the element at index `nth` of collection. +// If `nth` is negative, it returns the nth element from the end. +// If `nth` is out of slice bounds, it returns the zero value (empty value) for that type. +func NthOrEmpty[T any, N constraints.Integer](collection []T, nth N) T { + value, err := Nth(collection, nth) + if err != nil { + var zeroValue T + return zeroValue + } + return value +} + +// randomIntGenerator is a function that should return a random integer in the range [0, n) +// where n is the parameter passed to the randomIntGenerator. +type randomIntGenerator func(n int) int + +// Sample returns a random item from collection. +func Sample[T any](collection []T) T { + result := SampleBy(collection, rand.IntN) + return result +} + +// SampleBy returns a random item from collection, using randomIntGenerator as the random index generator. +func SampleBy[T any](collection []T, randomIntGenerator randomIntGenerator) T { + size := len(collection) + if size == 0 { + return Empty[T]() + } + return collection[randomIntGenerator(size)] +} + +// Samples returns N random unique items from collection. +func Samples[T any, Slice ~[]T](collection Slice, count int) Slice { + results := SamplesBy(collection, count, rand.IntN) + return results +} + +// SamplesBy returns N random unique items from collection, using randomIntGenerator as the random index generator. +func SamplesBy[T any, Slice ~[]T](collection Slice, count int, randomIntGenerator randomIntGenerator) Slice { + size := len(collection) + + copy := append(Slice{}, collection...) + + results := Slice{} + + for i := 0; i < size && i < count; i++ { + copyLength := size - i + + index := randomIntGenerator(size - i) + results = append(results, copy[index]) + + // Removes element. + // It is faster to swap with last element and remove it. + copy[index] = copy[copyLength-1] + copy = copy[:copyLength-1] + } + + return results +} |
