Skip to content

Commit

Permalink
优化对称差集,交集实现
Browse files Browse the repository at this point in the history
  • Loading branch information
johnwongx committed Aug 31, 2023
1 parent 4a09f17 commit 19d680a
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 71 deletions.
2 changes: 1 addition & 1 deletion slice/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
)

func TestAdd(t *testing.T) {
// Delete 主要依赖于 internal/slice.Delete 来保证正确性
// Add 主要依赖于 internal/slice.Add 来保证正确性
testCases := []struct {
name string
slice []int
Expand Down
11 changes: 5 additions & 6 deletions slice/intersect.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ func IntersectSet[T comparable](src []T, dst []T) []T {
// 已去重
func IntersectSetFunc[T any](src []T, dst []T, equal equalFunc[T]) []T {
var ret = make([]T, 0, len(src))
for _, valSrc := range src {
for _, valDst := range dst {
if equal(valDst, valSrc) {
ret = append(ret, valSrc)
break
}
for _, v := range dst {
if ContainsFunc[T](src, func(t T) bool {
return equal(t, v)
}) {
ret = append(ret, v)
}
}
return deduplicateFunc[T](ret, equal)
Expand Down
53 changes: 19 additions & 34 deletions slice/symmetric_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,60 +19,45 @@ package slice
// 返回值的元素顺序是不定的
func SymmetricDiffSet[T comparable](src, dst []T) []T {
srcMap, dstMap := toMap[T](src), toMap[T](dst)
for dstKey := range dstMap {
if _, exist := srcMap[dstKey]; exist {
// 删除共同元素,两者剩余的并集即为对称差
delete(dstMap, dstKey)
delete(srcMap, dstKey)
for k := range dstMap {
if _, ok := srcMap[k]; ok {
delete(srcMap, k)
} else {
srcMap[k] = struct{}{}
}
}

for k, v := range dstMap {
srcMap[k] = v
}
var ret = make([]T, 0, len(srcMap))
res := make([]T, 0, len(srcMap))
for k := range srcMap {
ret = append(ret, k)
res = append(res, k)
}

return ret
return res
}

// SymmetricDiffSetFunc 对称差集
// 你应该优先使用 SymmetricDiffSet
// 已去重
func SymmetricDiffSetFunc[T any](src, dst []T, equal equalFunc[T]) []T {
var interSection = make([]T, 0, min(len(src), len(dst)))
for _, valSrc := range src {
for _, valDst := range dst {
if equal(valSrc, valDst) {
interSection = append(interSection, valSrc)
break
}
}
}
res := []T{}

ret := make([]T, 0, len(src)+len(dst)-len(interSection)*2)
//找出在src不在dst的元素
for _, v := range src {
if !ContainsFunc[T](interSection, func(src T) bool {
return equal(src, v)
if !ContainsFunc[T](dst, func(t T) bool {
return equal(t, v)
}) {
ret = append(ret, v)
res = append(res, v)
}
}

//找出在dst不在src的元素
for _, v := range dst {
if !ContainsFunc[T](interSection, func(src T) bool {
return equal(src, v)
if !ContainsFunc[T](src, func(t T) bool {
return equal(t, v)
}) {
ret = append(ret, v)
res = append(res, v)
}
}
return deduplicateFunc[T](ret, equal)
}

func min(src, dst int) int {
if src > dst {
return dst
}
return src
return deduplicateFunc[T](res, equal)
}
138 changes: 108 additions & 30 deletions slice/symmetric_diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,70 @@ func TestSymmetricDiffSet(t *testing.T) {
want []int
}{
{
src: []int{1, 2, 4, 3},
dst: []int{4, 5, 6, 1},
want: []int{2, 3, 5, 6},
name: "normal test",
name: "no inter",
src: []int{1, 2, 3},
dst: []int{4, 5, 6},
want: []int{1, 2, 3, 4, 5, 6},
},
{
src: []int{1, 1, 2, 3, 4},
dst: []int{4, 5, 6, 1, 7, 6},
want: []int{3, 6, 7, 5, 2},
name: "deduplicate",
name: "part inter",
src: []int{1, 2, 3},
dst: []int{3, 4, 5},
want: []int{1, 2, 4, 5},
},
{
src: []int{},
dst: []int{1},
name: "src contain dst",
src: []int{1, 2, 3},
dst: []int{2, 3},
want: []int{1},
name: "src length is 0",
},
{
src: []int{1, 3, 5},
dst: []int{2, 4},
want: []int{1, 3, 2, 4, 5},
name: "not exist same ele",
name: "dst contain src",
src: []int{4},
dst: []int{4, 5, 6},
want: []int{5, 6},
},
{
name: "equal",
src: []int{1, 2, 3},
dst: []int{1, 2, 3},
want: []int{},
},
{
name: "dst empty",
src: []int{1, 2, 3},
dst: []int{},
want: []int{1, 2, 3},
},
{
name: "src empty",
src: []int{},
dst: []int{4, 5, 6},
want: []int{4, 5, 6},
},
{
name: "all empty",
src: []int{},
dst: []int{},
want: []int{},
},
{
name: "src nil",
src: nil,
dst: []int{4, 5, 6},
want: []int{4, 5, 6},
},
{
name: "dst nil",
src: []int{4, 5, 6},
dst: nil,
want: []int{4, 5, 6},
},
{
name: "both nil",
src: nil,
dst: nil,
want: []int{},
},
}
for _, tt := range tests {
Expand All @@ -73,31 +112,70 @@ func TestSymmetricDiffSetFunc(t *testing.T) {
want []int
}{
{
src: []int{1, 2, 3, 4},
dst: []int{4, 5, 6, 1},
want: []int{2, 3, 5, 6},
name: "normal test",
name: "no inter",
src: []int{1, 2, 3},
dst: []int{4, 5, 6},
want: []int{1, 2, 3, 4, 5, 6},
},
{
src: []int{1, 1, 2, 3, 4},
dst: []int{4, 5, 6, 1, 7, 6},
want: []int{3, 6, 7, 5, 2},
name: "deduplicate",
name: "part inter",
src: []int{1, 2, 3},
dst: []int{3, 4, 5},
want: []int{1, 2, 4, 5},
},
{
src: []int{},
dst: []int{1},
name: "src contain dst",
src: []int{1, 2, 3},
dst: []int{2, 3},
want: []int{1},
name: "src length is 0",
},
{
src: []int{1, 3, 5},
dst: []int{2, 4},
want: []int{1, 3, 2, 4, 5},
name: "not exist same ele",
name: "dst contain src",
src: []int{4},
dst: []int{4, 5, 6},
want: []int{5, 6},
},
{
name: "equal",
src: []int{1, 2, 3},
dst: []int{1, 2, 3},
want: []int{},
},
{
name: "dst empty",
src: []int{1, 2, 3},
dst: []int{},
want: []int{1, 2, 3},
},
{
name: "src empty",
src: []int{},
dst: []int{4, 5, 6},
want: []int{4, 5, 6},
},
{
name: "all empty",
src: []int{},
dst: []int{},
want: []int{},
},
{
name: "src nil",
src: nil,
dst: []int{4, 5, 6},
want: []int{4, 5, 6},
},
{
name: "dst nil",
src: []int{4, 5, 6},
dst: nil,
want: []int{4, 5, 6},
},
{
name: "both nil",
src: nil,
dst: nil,
want: []int{},
},
}
for _, tt := range tests {
Expand Down

0 comments on commit 19d680a

Please sign in to comment.