diff --git a/helper/slice/set.go b/helper/slice/set.go index e9e7cf2..c3b6972 100644 --- a/helper/slice/set.go +++ b/helper/slice/set.go @@ -53,6 +53,23 @@ func DiffByFn[T any](a []T, fn func(i, j T) bool, b ...[]T) (r []T) { return } +func DiffNewByFn[T, V any](a []T, fn func(i, j T) bool, fnV func(T) V, b ...[]T) (r []V) { + for _, t := range a { + f := false + for _, ts := range b { + if IsContainedByFn(ts, t, fn) { + f = true + break + } + } + if f { + continue + } + r = append(r, fnV(t)) + } + return +} + func Intersect[T comparable](a []T, b ...[]T) (r []T) { for _, t := range a { f := false @@ -87,6 +104,23 @@ func IntersectByFn[T any](a []T, fn func(i, j T) bool, b ...[]T) (r []T) { return } +func IntersectNewByFn[T, V any](a []T, fn func(i, j T) bool, fnV func(T) V, b ...[]T) (r []V) { + for _, t := range a { + f := false + for _, ts := range b { + if !IsContainedByFn(ts, t, fn) { + f = true + break + } + } + if f { + continue + } + r = append(r, fnV(t)) + } + return +} + func Unique[T comparable](a ...[]T) (r []T) { m := map[T]struct{}{} for _, ts := range a { diff --git a/helper/slice/set_test.go b/helper/slice/set_test.go index d0400c1..b4c7f06 100644 --- a/helper/slice/set_test.go +++ b/helper/slice/set_test.go @@ -83,6 +83,46 @@ func TestDiffByFn(t *testing.T) { } } +func TestDiffNewByFn(t *testing.T) { + type args[T x, V int] struct { + a []T + fn func(i, j T) bool + fnV func(T) V + b [][]T + } + type testCase[T x, V int] struct { + name string + args args[T, V] + wantR []V + } + tests := []testCase[x, int]{ + { + name: "t1", + args: args[x, int]{ + a: y(number.Range(1, 10, 1)), + fn: func(i, j x) bool { + return i.int == j.int + }, + fnV: func(v x) int { + return v.int + }, + b: [][]x{ + y(number.Range(3, 7, 1)), + y(number.Range(6, 9, 1)), + }, + }, + wantR: []int{1, 2, 10}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if gotR := DiffNewByFn(tt.args.a, tt.args.fn, tt.args.fnV, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) { + t.Errorf("DiffNewByFn() = %v, want %v", gotR, tt.wantR) + } + }) + } +} + func TestIntersect(t *testing.T) { type args[T int] struct { a []T @@ -148,6 +188,46 @@ func TestIntersectByFn(t *testing.T) { } } +func TestIntersectNewByFn(t *testing.T) { + type args[T x, V int] struct { + a []T + fn func(i, j T) bool + fnV func(T) V + b [][]T + } + type testCase[T x, V int] struct { + name string + args args[T, V] + wantR []V + } + tests := []testCase[x, int]{ + { + name: "t1", + args: args[x, int]{ + a: y(number.Range(1, 10, 1)), + fn: func(i, j x) bool { + return i.int == j.int + }, + fnV: func(v x) int { + return v.int + }, + b: [][]x{ + y(number.Range(3, 7, 1)), + y(number.Range(6, 9, 1)), + }, + }, + wantR: []int{6, 7}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if gotR := IntersectNewByFn(tt.args.a, tt.args.fn, tt.args.fnV, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) { + t.Errorf("IntersectNewByFn() = %v, want %v", gotR, tt.wantR) + } + }) + } +} + func TestUnique(t *testing.T) { type args[T int] struct { a [][]T