diff options
Diffstat (limited to 'vendor/github.com/samber/lo/intersect.go')
| -rw-r--r-- | vendor/github.com/samber/lo/intersect.go | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/vendor/github.com/samber/lo/intersect.go b/vendor/github.com/samber/lo/intersect.go new file mode 100644 index 00000000..c57bd817 --- /dev/null +++ b/vendor/github.com/samber/lo/intersect.go @@ -0,0 +1,265 @@ +package lo + +// Contains returns true if an element is present in a collection. +func Contains[T comparable](collection []T, element T) bool { + for i := range collection { + if collection[i] == element { + return true + } + } + + return false +} + +// ContainsBy returns true if predicate function return true. +func ContainsBy[T any](collection []T, predicate func(item T) bool) bool { + for i := range collection { + if predicate(collection[i]) { + return true + } + } + + return false +} + +// Every returns true if all elements of a subset are contained into a collection or if the subset is empty. +func Every[T comparable](collection []T, subset []T) bool { + for i := range subset { + if !Contains(collection, subset[i]) { + return false + } + } + + return true +} + +// EveryBy returns true if the predicate returns true for all elements in the collection or if the collection is empty. +func EveryBy[T any](collection []T, predicate func(item T) bool) bool { + for i := range collection { + if !predicate(collection[i]) { + return false + } + } + + return true +} + +// Some returns true if at least 1 element of a subset is contained into a collection. +// If the subset is empty Some returns false. +func Some[T comparable](collection []T, subset []T) bool { + for i := range subset { + if Contains(collection, subset[i]) { + return true + } + } + + return false +} + +// SomeBy returns true if the predicate returns true for any of the elements in the collection. +// If the collection is empty SomeBy returns false. +func SomeBy[T any](collection []T, predicate func(item T) bool) bool { + for i := range collection { + if predicate(collection[i]) { + return true + } + } + + return false +} + +// None returns true if no element of a subset are contained into a collection or if the subset is empty. +func None[T comparable](collection []T, subset []T) bool { + for i := range subset { + if Contains(collection, subset[i]) { + return false + } + } + + return true +} + +// NoneBy returns true if the predicate returns true for none of the elements in the collection or if the collection is empty. +func NoneBy[T any](collection []T, predicate func(item T) bool) bool { + for i := range collection { + if predicate(collection[i]) { + return false + } + } + + return true +} + +// Intersect returns the intersection between two collections. +func Intersect[T comparable, Slice ~[]T](list1 Slice, list2 Slice) Slice { + result := Slice{} + seen := map[T]struct{}{} + + for i := range list1 { + seen[list1[i]] = struct{}{} + } + + for i := range list2 { + if _, ok := seen[list2[i]]; ok { + result = append(result, list2[i]) + } + } + + return result +} + +// Difference returns the difference between two collections. +// The first value is the collection of element absent of list2. +// The second value is the collection of element absent of list1. +func Difference[T comparable, Slice ~[]T](list1 Slice, list2 Slice) (Slice, Slice) { + left := Slice{} + right := Slice{} + + seenLeft := map[T]struct{}{} + seenRight := map[T]struct{}{} + + for i := range list1 { + seenLeft[list1[i]] = struct{}{} + } + + for i := range list2 { + seenRight[list2[i]] = struct{}{} + } + + for i := range list1 { + if _, ok := seenRight[list1[i]]; !ok { + left = append(left, list1[i]) + } + } + + for i := range list2 { + if _, ok := seenLeft[list2[i]]; !ok { + right = append(right, list2[i]) + } + } + + return left, right +} + +// Union returns all distinct elements from given collections. +// result returns will not change the order of elements relatively. +func Union[T comparable, Slice ~[]T](lists ...Slice) Slice { + var capLen int + + for _, list := range lists { + capLen += len(list) + } + + result := make(Slice, 0, capLen) + seen := make(map[T]struct{}, capLen) + + for i := range lists { + for j := range lists[i] { + if _, ok := seen[lists[i][j]]; !ok { + seen[lists[i][j]] = struct{}{} + result = append(result, lists[i][j]) + } + } + } + + return result +} + +// Without returns slice excluding all given values. +func Without[T comparable, Slice ~[]T](collection Slice, exclude ...T) Slice { + excludeMap := make(map[T]struct{}, len(exclude)) + for i := range exclude { + excludeMap[exclude[i]] = struct{}{} + } + + result := make(Slice, 0, len(collection)) + for i := range collection { + if _, ok := excludeMap[collection[i]]; !ok { + result = append(result, collection[i]) + } + } + return result +} + +// WithoutBy filters a slice by excluding elements whose extracted keys match any in the exclude list. +// It returns a new slice containing only the elements whose keys are not in the exclude list. +func WithoutBy[T any, K comparable](collection []T, iteratee func(item T) K, exclude ...K) []T { + excludeMap := make(map[K]struct{}, len(exclude)) + for _, e := range exclude { + excludeMap[e] = struct{}{} + } + + result := make([]T, 0, len(collection)) + for _, item := range collection { + if _, ok := excludeMap[iteratee(item)]; !ok { + result = append(result, item) + } + } + return result +} + +// WithoutEmpty returns slice excluding zero values. +// +// Deprecated: Use lo.Compact instead. +func WithoutEmpty[T comparable, Slice ~[]T](collection Slice) Slice { + return Compact(collection) +} + +// WithoutNth returns slice excluding nth value. +func WithoutNth[T comparable, Slice ~[]T](collection Slice, nths ...int) Slice { + length := len(collection) + + toRemove := make(map[int]struct{}, len(nths)) + for i := range nths { + if nths[i] >= 0 && nths[i] <= length-1 { + toRemove[nths[i]] = struct{}{} + } + } + + result := make(Slice, 0, len(collection)) + for i := range collection { + if _, ok := toRemove[i]; !ok { + result = append(result, collection[i]) + } + } + + return result +} + +// ElementsMatch returns true if lists contain the same set of elements (including empty set). +// If there are duplicate elements, the number of appearances of each of them in both lists should match. +// The order of elements is not checked. +func ElementsMatch[T comparable, Slice ~[]T](list1 Slice, list2 Slice) bool { + return ElementsMatchBy(list1, list2, func(item T) T { return item }) +} + +// ElementsMatchBy returns true if lists contain the same set of elements' keys (including empty set). +// If there are duplicate keys, the number of appearances of each of them in both lists should match. +// The order of elements is not checked. +func ElementsMatchBy[T any, K comparable](list1 []T, list2 []T, iteratee func(item T) K) bool { + if len(list1) != len(list2) { + return false + } + + if len(list1) == 0 { + return true + } + + counters := make(map[K]int, len(list1)) + + for _, el := range list1 { + counters[iteratee(el)]++ + } + + for _, el := range list2 { + counters[iteratee(el)]-- + } + + for _, count := range counters { + if count != 0 { + return false + } + } + + return true +} |
