-
Notifications
You must be signed in to change notification settings - Fork 271
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add
Union
method and typesafe UnionStringMap
- Loading branch information
Showing
2 changed files
with
101 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package funk | ||
|
||
import ( | ||
"reflect" | ||
) | ||
|
||
// Union returns the union between two collections. | ||
func Union(collections ...interface{}) interface{} { | ||
// shortcut zero/single argument | ||
if len(collections) == 0 { | ||
return nil | ||
} else if len(collections) == 1 { | ||
return collections[0] | ||
} | ||
|
||
if !IsIteratee(collections[0]) { | ||
panic("Parameter must be a collection") | ||
} | ||
|
||
cType := reflect.TypeOf(collections[0]) | ||
zLen := 0 | ||
|
||
for i, x := range collections { | ||
xValue := reflect.ValueOf(x) | ||
xType := xValue.Type() | ||
if i > 0 && NotEqual(cType, xType) { | ||
panic("Parameters must have the same type") | ||
} | ||
|
||
zLen += xValue.Len() | ||
} | ||
|
||
if cType.Kind() == reflect.Map { | ||
zType := reflect.MapOf(cType.Key(), cType.Elem()) | ||
zMap := reflect.MakeMap(zType) | ||
|
||
for _, x := range collections { | ||
xIter := reflect.ValueOf(x).MapRange() | ||
for xIter.Next() { | ||
zMap.SetMapIndex(xIter.Key(), xIter.Value()) | ||
} | ||
} | ||
|
||
return zMap.Interface() | ||
} else { | ||
zType := reflect.SliceOf(cType.Elem()) | ||
zSlice := reflect.MakeSlice(zType, 0, 0) | ||
|
||
for _, x := range collections { | ||
xValue := reflect.ValueOf(x) | ||
zSlice = reflect.AppendSlice(zSlice, xValue) | ||
} | ||
|
||
return zSlice.Interface() | ||
} | ||
} | ||
|
||
// UnionStringMap returns the union between multiple string maps | ||
func UnionStringMap(x ...map[string]string) map[string]string { | ||
zMap := map[string]string{} | ||
for _, xMap := range x { | ||
for k, v := range xMap { | ||
zMap[k] = v | ||
} | ||
} | ||
return zMap | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package funk | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestUnion(t *testing.T) { | ||
is := assert.New(t) | ||
|
||
r := Union([]int{1, 2, 3, 4}, []int{2, 4, 6}) | ||
is.Equal(r, []int{1, 2, 3, 4, 2, 4, 6}) | ||
|
||
r = Union(map[int]int{1: 1, 2: 2}, map[int]int{1: 0, 3: 3}) | ||
is.Equal(r, map[int]int{1: 0, 2: 2, 3: 3}) | ||
} | ||
|
||
func TestUnionShortcut(t *testing.T) { | ||
is := assert.New(t) | ||
|
||
r := Union(nil) | ||
is.Nil(r) | ||
|
||
r = Union([]int{1, 2}) | ||
is.Equal(r, []int{1, 2}) | ||
} | ||
|
||
func TestUnionStringMap(t *testing.T) { | ||
is := assert.New(t) | ||
|
||
r := Union(map[string]string{"a": "a", "b": "b"}, map[string]string{"a": "z", "z": "a"}, map[string]string{"z": "z"}) | ||
is.Equal(r, map[string]string{"a": "z", "b": "b", "z": "z"}) | ||
} |