Skip to content

Commit

Permalink
Add helpers.AppendSliceUnique. Closes #85 (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
kaidaguerre committed Feb 13, 2024
1 parent 1fa35f4 commit 5f8aec6
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 2 deletions.
29 changes: 27 additions & 2 deletions helpers/reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ func DereferencePointer(val interface{}) interface{} {
}

/*
TODO: add support for multi-dimensional arrays
like - arr[1][2] arr[1][2][3] and so on..
TODO: add support for multi-dimensional arrays
like - arr[1][2] arr[1][2][3] and so on..
*/
func IsFieldArray(fieldName string) (string, int, bool) {
r := regexp.MustCompile(`^(.*)\[(\d+)\]$`)
Expand Down Expand Up @@ -146,3 +146,28 @@ func ExecuteMethod(item interface{}, methodName string) (returnValues []interfac
}
return
}

// StructToMap uses reflection to convert a struct to a map
func StructToMap(s any) map[string]any {
result := make(map[string]any)
val := reflect.ValueOf(s)

// We only accept structs
if val.Kind() == reflect.Ptr {
val = val.Elem()
}

if val.Kind() != reflect.Struct {
fmt.Println("Expecting a struct")
return nil
}

for i := 0; i < val.NumField(); i++ {
field := val.Type().Field(i)
value := val.Field(i).Interface()

result[field.Name] = value
}

return result
}
18 changes: 18 additions & 0 deletions helpers/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,21 @@ func ToTypedSlice[T any](input []any) []T {
}
return res
}

// AppendSliceUnique appends elements from slice2 to slice1, omitting duplicates.
func AppendSliceUnique[T comparable](slice1, slice2 []T) []T {
// Map existing elements of slice1 for quick lookup
exists := SliceToLookup(slice1)
result := make([]T, len(slice1))
copy(result, slice1)

// Check each element in slice2; if not a duplicate, append it to the result
for _, item := range slice2 {
if _, dupe := exists[item]; !dupe {
result = append(result, item)
exists[item] = struct{}{}
}
}

return result
}
55 changes: 55 additions & 0 deletions helpers/slice_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package helpers

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestAppendUnique(t *testing.T) {
type args[T comparable] struct {
slice1 []T
slice2 []T
}
type testCase[T comparable] struct {
name string
args args[T]
want []T
}
tests := []testCase[string]{
{
name: "empty slices",
args: args[string]{slice1: []string{}, slice2: []string{}},
want: []string{},
},
{
name: "empty slice1",
args: args[string]{slice1: []string{}, slice2: []string{"a", "b"}},
want: []string{"a", "b"},
},
{
name: "empty slice2",
args: args[string]{slice1: []string{"a", "b"}, slice2: []string{}},
want: []string{"a", "b"},
},
{
name: "no duplicates",
args: args[string]{slice1: []string{"a", "b"}, slice2: []string{"c", "d"}},
want: []string{"a", "b", "c", "d"},
},
{
name: "duplicates",
args: args[string]{slice1: []string{"a", "b"}, slice2: []string{"b", "c"}},
want: []string{"a", "b", "c"},
},
{
name: "duplicates in both slices",
args: args[string]{slice1: []string{"a", "b", "c"}, slice2: []string{"b", "c", "d"}},
want: []string{"a", "b", "c", "d"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, AppendSliceUnique(tt.args.slice1, tt.args.slice2), "AppendSliceUnique(%v, %v)", tt.args.slice1, tt.args.slice2)
})
}
}

0 comments on commit 5f8aec6

Please sign in to comment.