Skip to content

Commit

Permalink
feat: add the func goDashMap
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenvantuan2391996 committed Aug 6, 2023
1 parent 449b5b4 commit d86be6e
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 0 deletions.
41 changes: 41 additions & 0 deletions collection/map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package collection

import (
"reflect"

"github.com/warriors-vn/go-dash/constants"
)

// goDashMap applies the iteratee function to each element in the input array and returns a new slice of results.
// It takes an array-like data structure and an iteratee function that operates on each element.
// The iteratee function should have the signature func(elementType) mappedElementType.
// The function returns a new slice of mapped elements and an error if any occurs.
func goDashMap(array, iteratee interface{}) (interface{}, error) {
arrValue, iterateeValue := reflect.ValueOf(array), reflect.ValueOf(iteratee)

if arrValue.Kind() != reflect.Slice && arrValue.Kind() != reflect.Array {
return nil, constants.ErrNotSlice
}

if iterateeValue.Kind() != reflect.Func {
return nil, constants.ErrNotFunction
}

numParams := iterateeValue.Type().NumIn()
if numParams != 1 {
return nil, constants.ErrNotSupport
}

kind, result := iterateeValue.Type().In(0).Kind(), reflect.MakeSlice(arrValue.Type(), 0, 0)
if kind == reflect.Interface {
return nil, constants.ErrNotSupport
}
for i := 0; i < arrValue.Len(); i++ {
res := iterateeValue.Call([]reflect.Value{reflect.ValueOf(arrValue.Index(i).Interface())})
if len(res) > 0 && res[0].Kind() == kind {
result = reflect.Append(result, res[0])
}
}

return result.Interface(), nil
}
82 changes: 82 additions & 0 deletions collection/map_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package collection

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/warriors-vn/go-dash/constants"
)

func Test_goDashMap_valid_int(t *testing.T) {
result, err := goDashMap([]int{1, 2, 3, 4}, func(n int) int {
return n * n
})

assert.Equal(t, []int{1, 4, 9, 16}, result)
assert.Nil(t, err)
}

func Test_goDashMap_valid_response_func_invalid(t *testing.T) {
result, err := goDashMap([]int{1, 2, 3, 4}, func(n int) bool {
return n%2 == 0
})

assert.Equal(t, []int{}, result)
assert.Nil(t, err)
}

func Test_goDashMap_valid_string(t *testing.T) {
result, err := goDashMap([]string{"a", "b", "c"}, func(n string) string {
return n + n
})

assert.Equal(t, []string{"aa", "bb", "cc"}, result)
assert.Nil(t, err)
}

func Test_goDashMap_valid_struct(t *testing.T) {
type User struct {
Name string
Age int
}
result, err := goDashMap([]*User{{Name: "Kakalot", Age: 26}, {Name: "Vegeta", Age: 27}, {Name: "Trunk", Age: 10}}, func(n *User) *User {
return &User{Name: n.Name, Age: n.Age * 2}
})

assert.Equal(t, []*User{{Name: "Kakalot", Age: 52}, {Name: "Vegeta", Age: 54}, {Name: "Trunk", Age: 20}}, result)
assert.Nil(t, err)
}

func Test_goDashMap_invalid_array_not_slice(t *testing.T) {
result, err := goDashMap(true, func(n int) int {
return n * 2
})

assert.Equal(t, nil, result)
assert.Equal(t, constants.ErrNotSlice, err)
}

func Test_goDashMap_invalid_predicate_not_func(t *testing.T) {
result, err := goDashMap([]string{"a", "b", "c"}, true)

assert.Equal(t, nil, result)
assert.Equal(t, constants.ErrNotFunction, err)
}

func Test_goDashMap_invalid_param_predicate_limit(t *testing.T) {
result, err := goDashMap([]string{"a", "b", "c"}, func(n string, m int) bool {
return n == "a" || m%2 == 0
})

assert.Equal(t, nil, result)
assert.Equal(t, constants.ErrNotSupport, err)
}

func Test_goDashMap_invalid_interface(t *testing.T) {
result, err := goDashMap([]interface{}{"a", "b", "c"}, func(n interface{}) interface{} {
return n
})

assert.Equal(t, nil, result)
assert.Equal(t, constants.ErrNotSupport, err)
}

0 comments on commit d86be6e

Please sign in to comment.