github.com/kazu/loncha@v0.6.3/intersect.go (about) 1 //go:build go1.18 2 // +build go1.18 3 4 package loncha 5 6 import "sort" 7 8 type IntersectOpt struct { 9 Uniq bool 10 } 11 12 // Intersect ... intersection between 2 slice. 13 func Intersect[T comparable](slice1, slice2 []T, opts ...Opt[IntersectOpt]) (result []T) { 14 15 param, fn := MergeOpts(opts...) 16 defer fn(param) 17 18 exists := map[T]bool{} 19 already := map[T]bool{} 20 21 for _, v := range slice1 { 22 exists[v] = true 23 } 24 25 result = make([]T, 0, len(exists)) 26 27 for _, v := range slice2 { 28 if param.Param.Uniq && already[v] { 29 continue 30 } 31 32 if exists[v] { 33 result = append(result, v) 34 already[v] = true 35 } 36 } 37 return 38 } 39 40 // Ordered ... copy from https://github.com/golang/go/blob/go1.18.3/test/typeparam/ordered.go 41 type Ordered interface { 42 ~int | ~int8 | ~int16 | ~int32 | ~int64 | 43 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | 44 ~float32 | ~float64 | 45 ~string 46 } 47 48 type IdentFunc[T any, V Ordered] func(slice []T, i int) V 49 50 // IntersectSorted ... intersection between 2 sorted slice 51 func IntersectSorted[T any, V Ordered](slice1, slice2 []T, IdentFn IdentFunc[T, V]) (result []T) { 52 53 jn := 0 54 for i, v := range slice1 { 55 key := IdentFn(slice1, i) 56 idx := sort.Search(len(slice2)-jn, func(j int) bool { 57 return IdentFn(slice2, j+jn) >= key 58 }) 59 if idx < len(slice2) && IdentFn(slice2, idx) == key { 60 result = append(result, v) 61 jn = idx 62 } 63 } 64 return result 65 }