Skip to content

Commit

Permalink
feat: add Diff feature to gmap (#2774)
Browse files Browse the repository at this point in the history
  • Loading branch information
LonelySally authored Jul 20, 2023
1 parent 0d52386 commit 4ad508c
Show file tree
Hide file tree
Showing 14 changed files with 325 additions and 0 deletions.
26 changes: 26 additions & 0 deletions container/gmap/gmap_hash_any_any_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
"github.com/gogf/gf/v2/util/gconv"
"reflect"
)

// AnyAnyMap wraps map type `map[interface{}]interface{}` and provides more map features.
Expand Down Expand Up @@ -535,3 +536,28 @@ func (m *AnyAnyMap) IsSubOf(other *AnyAnyMap) bool {
}
return true
}

// Diff compares current map `m` with map `other` and returns their different keys.
// The returned `addedKeys` are the keys that are in map `m` but not in map `other`.
// The returned `removedKeys` are the keys that are in map `other` but not in map `m`.
// The returned `updatedKeys` are the keys that are both in map `m` and `other` but their values and not equal (`!=`).
func (m *AnyAnyMap) Diff(other *AnyAnyMap) (addedKeys, removedKeys, updatedKeys []interface{}) {
m.mu.RLock()
defer m.mu.RUnlock()
other.mu.RLock()
defer other.mu.RUnlock()

for key := range m.data {
if _, ok := other.data[key]; !ok {
removedKeys = append(removedKeys, key)
} else if !reflect.DeepEqual(m.data[key], other.data[key]) {
updatedKeys = append(updatedKeys, key)
}
}
for key := range other.data {
if _, ok := m.data[key]; !ok {
addedKeys = append(addedKeys, key)
}
}
return
}
26 changes: 26 additions & 0 deletions container/gmap/gmap_hash_int_any_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
"github.com/gogf/gf/v2/util/gconv"
"reflect"
)

// IntAnyMap implements map[int]interface{} with RWMutex that has switch.
Expand Down Expand Up @@ -536,3 +537,28 @@ func (m *IntAnyMap) IsSubOf(other *IntAnyMap) bool {
}
return true
}

// Diff compares current map `m` with map `other` and returns their different keys.
// The returned `addedKeys` are the keys that are in map `m` but not in map `other`.
// The returned `removedKeys` are the keys that are in map `other` but not in map `m`.
// The returned `updatedKeys` are the keys that are both in map `m` and `other` but their values and not equal (`!=`).
func (m *IntAnyMap) Diff(other *IntAnyMap) (addedKeys, removedKeys, updatedKeys []int) {
m.mu.RLock()
defer m.mu.RUnlock()
other.mu.RLock()
defer other.mu.RUnlock()

for key := range m.data {
if _, ok := other.data[key]; !ok {
removedKeys = append(removedKeys, key)
} else if !reflect.DeepEqual(m.data[key], other.data[key]) {
updatedKeys = append(updatedKeys, key)
}
}
for key := range other.data {
if _, ok := m.data[key]; !ok {
addedKeys = append(addedKeys, key)
}
}
return
}
25 changes: 25 additions & 0 deletions container/gmap/gmap_hash_int_int_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,3 +506,28 @@ func (m *IntIntMap) IsSubOf(other *IntIntMap) bool {
}
return true
}

// Diff compares current map `m` with map `other` and returns their different keys.
// The returned `addedKeys` are the keys that are in map `m` but not in map `other`.
// The returned `removedKeys` are the keys that are in map `other` but not in map `m`.
// The returned `updatedKeys` are the keys that are both in map `m` and `other` but their values and not equal (`!=`).
func (m *IntIntMap) Diff(other *IntIntMap) (addedKeys, removedKeys, updatedKeys []int) {
m.mu.RLock()
defer m.mu.RUnlock()
other.mu.RLock()
defer other.mu.RUnlock()

for key := range m.data {
if _, ok := other.data[key]; !ok {
removedKeys = append(removedKeys, key)
} else if m.data[key] != other.data[key] {
updatedKeys = append(updatedKeys, key)
}
}
for key := range other.data {
if _, ok := m.data[key]; !ok {
addedKeys = append(addedKeys, key)
}
}
return
}
25 changes: 25 additions & 0 deletions container/gmap/gmap_hash_int_str_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,3 +506,28 @@ func (m *IntStrMap) IsSubOf(other *IntStrMap) bool {
}
return true
}

// Diff compares current map `m` with map `other` and returns their different keys.
// The returned `addedKeys` are the keys that are in map `m` but not in map `other`.
// The returned `removedKeys` are the keys that are in map `other` but not in map `m`.
// The returned `updatedKeys` are the keys that are both in map `m` and `other` but their values and not equal (`!=`).
func (m *IntStrMap) Diff(other *IntStrMap) (addedKeys, removedKeys, updatedKeys []int) {
m.mu.RLock()
defer m.mu.RUnlock()
other.mu.RLock()
defer other.mu.RUnlock()

for key := range m.data {
if _, ok := other.data[key]; !ok {
removedKeys = append(removedKeys, key)
} else if m.data[key] != other.data[key] {
updatedKeys = append(updatedKeys, key)
}
}
for key := range other.data {
if _, ok := m.data[key]; !ok {
addedKeys = append(addedKeys, key)
}
}
return
}
26 changes: 26 additions & 0 deletions container/gmap/gmap_hash_str_any_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
"github.com/gogf/gf/v2/util/gconv"
"reflect"
)

// StrAnyMap implements map[string]interface{} with RWMutex that has switch.
Expand Down Expand Up @@ -522,3 +523,28 @@ func (m *StrAnyMap) IsSubOf(other *StrAnyMap) bool {
}
return true
}

// Diff compares current map `m` with map `other` and returns their different keys.
// The returned `addedKeys` are the keys that are in map `m` but not in map `other`.
// The returned `removedKeys` are the keys that are in map `other` but not in map `m`.
// The returned `updatedKeys` are the keys that are both in map `m` and `other` but their values and not equal (`!=`).
func (m *StrAnyMap) Diff(other *StrAnyMap) (addedKeys, removedKeys, updatedKeys []string) {
m.mu.RLock()
defer m.mu.RUnlock()
other.mu.RLock()
defer other.mu.RUnlock()

for key := range m.data {
if _, ok := other.data[key]; !ok {
removedKeys = append(removedKeys, key)
} else if !reflect.DeepEqual(m.data[key], other.data[key]) {
updatedKeys = append(updatedKeys, key)
}
}
for key := range other.data {
if _, ok := m.data[key]; !ok {
addedKeys = append(addedKeys, key)
}
}
return
}
25 changes: 25 additions & 0 deletions container/gmap/gmap_hash_str_int_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,3 +510,28 @@ func (m *StrIntMap) IsSubOf(other *StrIntMap) bool {
}
return true
}

// Diff compares current map `m` with map `other` and returns their different keys.
// The returned `addedKeys` are the keys that are in map `m` but not in map `other`.
// The returned `removedKeys` are the keys that are in map `other` but not in map `m`.
// The returned `updatedKeys` are the keys that are both in map `m` and `other` but their values and not equal (`!=`).
func (m *StrIntMap) Diff(other *StrIntMap) (addedKeys, removedKeys, updatedKeys []string) {
m.mu.RLock()
defer m.mu.RUnlock()
other.mu.RLock()
defer other.mu.RUnlock()

for key := range m.data {
if _, ok := other.data[key]; !ok {
removedKeys = append(removedKeys, key)
} else if m.data[key] != other.data[key] {
updatedKeys = append(updatedKeys, key)
}
}
for key := range other.data {
if _, ok := m.data[key]; !ok {
addedKeys = append(addedKeys, key)
}
}
return
}
25 changes: 25 additions & 0 deletions container/gmap/gmap_hash_str_str_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,3 +499,28 @@ func (m *StrStrMap) IsSubOf(other *StrStrMap) bool {
}
return true
}

// Diff compares current map `m` with map `other` and returns their different keys.
// The returned `addedKeys` are the keys that are in map `m` but not in map `other`.
// The returned `removedKeys` are the keys that are in map `other` but not in map `m`.
// The returned `updatedKeys` are the keys that are both in map `m` and `other` but their values and not equal (`!=`).
func (m *StrStrMap) Diff(other *StrStrMap) (addedKeys, removedKeys, updatedKeys []string) {
m.mu.RLock()
defer m.mu.RUnlock()
other.mu.RLock()
defer other.mu.RUnlock()

for key := range m.data {
if _, ok := other.data[key]; !ok {
removedKeys = append(removedKeys, key)
} else if m.data[key] != other.data[key] {
updatedKeys = append(updatedKeys, key)
}
}
for key := range other.data {
if _, ok := m.data[key]; !ok {
addedKeys = append(addedKeys, key)
}
}
return
}
21 changes: 21 additions & 0 deletions container/gmap/gmap_z_unit_hash_any_any_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,3 +406,24 @@ func Test_AnyAnyMap_IsSubOf(t *testing.T) {
t.Assert(m2.IsSubOf(m2), true)
})
}

func Test_AnyAnyMap_Diff(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewAnyAnyMapFrom(g.MapAnyAny{
"0": "v0",
"1": "v1",
2: "v2",
3: 3,
})
m2 := gmap.NewAnyAnyMapFrom(g.MapAnyAny{
"0": "v0",
2: "v2",
3: "v3",
4: "v4",
})
addedKeys, removedKeys, updatedKeys := m1.Diff(m2)
t.Assert(addedKeys, []interface{}{4})
t.Assert(removedKeys, []interface{}{"1"})
t.Assert(updatedKeys, []interface{}{3})
})
}
21 changes: 21 additions & 0 deletions container/gmap/gmap_z_unit_hash_int_any_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,24 @@ func Test_IntAnyMap_IsSubOf(t *testing.T) {
t.Assert(m2.IsSubOf(m2), true)
})
}

func Test_IntAnyMap_Diff(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewIntAnyMapFrom(g.MapIntAny{
0: "v0",
1: "v1",
2: "v2",
3: 3,
})
m2 := gmap.NewIntAnyMapFrom(g.MapIntAny{
0: "v0",
2: "v2",
3: "v3",
4: "v4",
})
addedKeys, removedKeys, updatedKeys := m1.Diff(m2)
t.Assert(addedKeys, []int{4})
t.Assert(removedKeys, []int{1})
t.Assert(updatedKeys, []int{3})
})
}
21 changes: 21 additions & 0 deletions container/gmap/gmap_z_unit_hash_int_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,24 @@ func Test_IntIntMap_IsSubOf(t *testing.T) {
t.Assert(m2.IsSubOf(m2), true)
})
}

func Test_IntIntMap_Diff(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewIntIntMapFrom(g.MapIntInt{
0: 0,
1: 1,
2: 2,
3: 3,
})
m2 := gmap.NewIntIntMapFrom(g.MapIntInt{
0: 0,
2: 2,
3: 31,
4: 4,
})
addedKeys, removedKeys, updatedKeys := m1.Diff(m2)
t.Assert(addedKeys, []int{4})
t.Assert(removedKeys, []int{1})
t.Assert(updatedKeys, []int{3})
})
}
21 changes: 21 additions & 0 deletions container/gmap/gmap_z_unit_hash_int_str_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,3 +462,24 @@ func Test_IntStrMap_IsSubOf(t *testing.T) {
t.Assert(m2.IsSubOf(m2), true)
})
}

func Test_IntStrMap_Diff(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewIntStrMapFrom(g.MapIntStr{
0: "0",
1: "1",
2: "2",
3: "3",
})
m2 := gmap.NewIntStrMapFrom(g.MapIntStr{
0: "0",
2: "2",
3: "31",
4: "4",
})
addedKeys, removedKeys, updatedKeys := m1.Diff(m2)
t.Assert(addedKeys, []int{4})
t.Assert(removedKeys, []int{1})
t.Assert(updatedKeys, []int{3})
})
}
21 changes: 21 additions & 0 deletions container/gmap/gmap_z_unit_hash_str_any_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,24 @@ func Test_StrAnyMap_IsSubOf(t *testing.T) {
t.Assert(m2.IsSubOf(m2), true)
})
}

func Test_StrAnyMap_Diff(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewStrAnyMapFrom(g.MapStrAny{
"0": "v0",
"1": "v1",
"2": "v2",
"3": 3,
})
m2 := gmap.NewStrAnyMapFrom(g.MapStrAny{
"0": "v0",
"2": "v2",
"3": "v3",
"4": "v4",
})
addedKeys, removedKeys, updatedKeys := m1.Diff(m2)
t.Assert(addedKeys, []string{"4"})
t.Assert(removedKeys, []string{"1"})
t.Assert(updatedKeys, []string{"3"})
})
}
21 changes: 21 additions & 0 deletions container/gmap/gmap_z_unit_hash_str_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,3 +404,24 @@ func Test_StrIntMap_IsSubOf(t *testing.T) {
t.Assert(m2.IsSubOf(m2), true)
})
}

func Test_StrIntMap_Diff(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewStrIntMapFrom(g.MapStrInt{
"0": 0,
"1": 1,
"2": 2,
"3": 3,
})
m2 := gmap.NewStrIntMapFrom(g.MapStrInt{
"0": 0,
"2": 2,
"3": 31,
"4": 4,
})
addedKeys, removedKeys, updatedKeys := m1.Diff(m2)
t.Assert(addedKeys, []string{"4"})
t.Assert(removedKeys, []string{"1"})
t.Assert(updatedKeys, []string{"3"})
})
}
Loading

0 comments on commit 4ad508c

Please sign in to comment.