Skip to content

Commit

Permalink
Merge pull request #133 from adammw/adammw/intersection-map
Browse files Browse the repository at this point in the history
feat: support Difference for maps
  • Loading branch information
thoas authored Nov 12, 2021
2 parents 2f4b463 + b3b24a2 commit 658cf47
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 19 deletions.
67 changes: 48 additions & 19 deletions intersection.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ func IntersectString(x []string, y []string) []string {

// Difference returns the difference between two collections.
func Difference(x interface{}, y interface{}) (interface{}, interface{}) {
if !IsCollection(x) {
panic("First parameter must be a collection")
if !IsIteratee(x) {
panic("First parameter must be an iteratee")
}
if !IsCollection(y) {
panic("Second parameter must be a collection")
if !IsIteratee(y) {
panic("Second parameter must be an iteratee")
}

xValue := reflect.ValueOf(x)
Expand All @@ -90,26 +90,55 @@ func Difference(x interface{}, y interface{}) (interface{}, interface{}) {
panic("Parameters must have the same type")
}

leftType := reflect.SliceOf(xType.Elem())
leftSlice := reflect.MakeSlice(leftType, 0, 0)
rightType := reflect.SliceOf(yType.Elem())
rightSlice := reflect.MakeSlice(rightType, 0, 0)
if xType.Kind() == reflect.Map {
leftType := reflect.MapOf(xType.Key(), xType.Elem())
rightType := reflect.MapOf(xType.Key(), xType.Elem())
leftMap := reflect.MakeMap(leftType)
rightMap := reflect.MakeMap(rightType)

xIter := xValue.MapRange()
for xIter.Next() {
k := xIter.Key()
xv := xIter.Value()
yv := yValue.MapIndex(k)
equalTo := equal(xv.Interface(), true)
if !yv.IsValid() || !equalTo(yv, yv) {
leftMap.SetMapIndex(k, xv)
}
}

for i := 0; i < xValue.Len(); i++ {
v := xValue.Index(i).Interface()
if !Contains(y, v) {
leftSlice = reflect.Append(leftSlice, xValue.Index(i))
yIter := yValue.MapRange()
for yIter.Next() {
k := yIter.Key()
yv := yIter.Value()
xv := xValue.MapIndex(k)
equalTo := equal(yv.Interface(), true)
if !xv.IsValid() || !equalTo(xv, xv) {
rightMap.SetMapIndex(k, yv)
}
}
return leftMap.Interface(), rightMap.Interface()
} else {
leftType := reflect.SliceOf(xType.Elem())
rightType := reflect.SliceOf(yType.Elem())
leftSlice := reflect.MakeSlice(leftType, 0, 0)
rightSlice := reflect.MakeSlice(rightType, 0, 0)

for i := 0; i < xValue.Len(); i++ {
v := xValue.Index(i).Interface()
if !Contains(y, v) {
leftSlice = reflect.Append(leftSlice, xValue.Index(i))
}
}
}

for i := 0; i < yValue.Len(); i++ {
v := yValue.Index(i).Interface()
if !Contains(x, v) {
rightSlice = reflect.Append(rightSlice, yValue.Index(i))
for i := 0; i < yValue.Len(); i++ {
v := yValue.Index(i).Interface()
if !Contains(x, v) {
rightSlice = reflect.Append(rightSlice, yValue.Index(i))
}
}
return leftSlice.Interface(), rightSlice.Interface()
}

return leftSlice.Interface(), rightSlice.Interface()
}

// DifferenceString returns the difference between two collections of strings.
Expand Down
4 changes: 4 additions & 0 deletions intersection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ func TestDifference(t *testing.T) {
r1, r2 = Difference([]string{"foo", "bar", "hello", "bar"}, []string{"foo", "bar"})
is.Equal(r1, []string{"hello"})
is.Equal(r2, []string{})

r1, r2 = Difference(map[string]string{"foo": "bar", "hello": "baz"}, map[string]string{"foo": "bar", "bar": "baz"})
is.Equal(r1, map[string]string{"hello": "baz"})
is.Equal(r2, map[string]string{"bar": "baz"})
}

func TestDifferenceString(t *testing.T) {
Expand Down

0 comments on commit 658cf47

Please sign in to comment.