github.com/MontFerret/ferret@v0.18.0/pkg/stdlib/arrays/intersection.go (about) 1 package arrays 2 3 import ( 4 "context" 5 6 "github.com/MontFerret/ferret/pkg/runtime/core" 7 "github.com/MontFerret/ferret/pkg/runtime/values" 8 "github.com/MontFerret/ferret/pkg/runtime/values/types" 9 ) 10 11 // INTERSECTION return the intersection of all arrays specified. 12 // The result is an array of values that occur in all arguments. 13 // The element order is random. Duplicates are removed. 14 // @param {Any[], repeated} arrays - An arbitrary number of arrays as multiple arguments (at least 2). 15 // @return {Any[]} - A single array with only the elements, which exist in all provided arrays. 16 func Intersection(_ context.Context, args ...core.Value) (core.Value, error) { 17 return sections(args, len(args)) 18 } 19 20 func sections(args []core.Value, count int) (core.Value, error) { 21 err := core.ValidateArgs(args, 2, core.MaxArgs) 22 23 if err != nil { 24 return values.None, err 25 } 26 27 intersections := make(map[uint64][]core.Value) 28 capacity := len(args) 29 30 for _, i := range args { 31 err := core.ValidateType(i, types.Array) 32 33 if err != nil { 34 return values.None, err 35 } 36 37 arr := i.(*values.Array) 38 39 arr.ForEach(func(value core.Value, idx int) bool { 40 h := value.Hash() 41 42 bucket, exists := intersections[h] 43 44 if !exists { 45 bucket = make([]core.Value, 0, 5) 46 } 47 48 bucket = append(bucket, value) 49 intersections[h] = bucket 50 bucketLen := len(bucket) 51 52 if bucketLen > capacity { 53 capacity = bucketLen 54 } 55 56 return true 57 }) 58 } 59 60 result := values.NewArray(capacity) 61 required := count 62 63 for _, bucket := range intersections { 64 if len(bucket) == required { 65 result.Push(bucket[0]) 66 } 67 } 68 69 return result, nil 70 }