From bf7ffbfa8da46563dc7151ccb9e753d2b7195d7b Mon Sep 17 00:00:00 2001 From: dudaodong Date: Thu, 31 Mar 2022 16:56:12 +0800 Subject: [PATCH] feat: add Intersect func --- maputil/map.go | 35 +++++++++++++++++++++++++++++++++++ maputil/map_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/maputil/map.go b/maputil/map.go index 951ba11..a22988f 100644 --- a/maputil/map.go +++ b/maputil/map.go @@ -4,6 +4,8 @@ // Package maputil includes some functions to manipulate map. package maputil +import "reflect" + // Keys returns a slice of the map's keys func Keys[K comparable, V any](m map[K]V) []K { keys := make([]K, 0, len(m)) @@ -57,3 +59,36 @@ func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) } return res } + +// Intersect iterates over maps, return a new map of key and value pairs in all give maps +func Intersect[K comparable, V any](maps ...map[K]V) map[K]V { + if len(maps) == 0 { + return map[K]V{} + } + if len(maps) == 1 { + return maps[0] + } + + res := make(map[K]V) + + reducer := func(m1, m2 map[K]V) map[K]V { + m := make(map[K]V) + for k, v1 := range m1 { + if v2, ok := m2[k]; ok && reflect.DeepEqual(v1, v2) { + m[k] = v1 + } + } + return m + } + + reduceMaps := make([]map[K]V, 2, 2) + res = reducer(maps[0], maps[1]) + + for i := 2; i < len(maps); i++ { + reduceMaps[0] = res + reduceMaps[1] = maps[i] + res = reducer(reduceMaps[0], reduceMaps[1]) + } + + return res +} diff --git a/maputil/map_test.go b/maputil/map_test.go index 97a7233..7957c09 100644 --- a/maputil/map_test.go +++ b/maputil/map_test.go @@ -103,3 +103,30 @@ func TestFilter(t *testing.T) { "d": 4, }, acturl) } + +func TestIntersect(t *testing.T) { + assert := internal.NewAssert(t, "TestIntersect") + + m1 := map[string]int{ + "a": 1, + "b": 2, + "c": 3, + } + + m2 := map[string]int{ + "a": 1, + "b": 2, + "c": 6, + "d": 7, + } + + m3 := map[string]int{ + "a": 1, + "b": 9, + "e": 9, + } + + assert.Equal(map[string]int{"a": 1, "b": 2, "c": 3}, Intersect(m1)) + assert.Equal(map[string]int{"a": 1, "b": 2}, Intersect(m1, m2)) + assert.Equal(map[string]int{"a": 1}, Intersect(m1, m2, m3)) +}