Skip to content

Commit

Permalink
feat: Value(res interface{})支持传入reflect.Value
Browse files Browse the repository at this point in the history
  • Loading branch information
ahl5esoft committed May 19, 2021
1 parent 94ea294 commit 2827f6b
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 80 deletions.
56 changes: 44 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
\_/__/
```

# Underscore.go [![GoDoc](https://godoc.org/github.com/ahl5esoft/golang-underscore?status.svg)](https://godoc.org/github.com/ahl5esoft/golang-underscore) [![Go Report Card](https://goreportcard.com/badge/github.com/ahl5esoft/golang-underscore)](https://goreportcard.com/report/github.com/ahl5esoft/golang-underscore) ![Version](https://img.shields.io/badge/version-2.3.0-green.svg)
# Underscore.go [![GoDoc](https://godoc.org/github.com/ahl5esoft/golang-underscore?status.svg)](https://godoc.org/github.com/ahl5esoft/golang-underscore) [![Go Report Card](https://goreportcard.com/badge/github.com/ahl5esoft/golang-underscore)](https://goreportcard.com/report/github.com/ahl5esoft/golang-underscore) ![Version](https://img.shields.io/badge/version-2.4.0-green.svg)
like <a href="http://underscorejs.org/">underscore.js</a> and C# LINQ, but for Go

## Installation
Expand Down Expand Up @@ -57,6 +57,7 @@ like <a href="http://underscorejs.org/">underscore.js</a> and C# LINQ, but for G
* [`Sort`](#order), [`SortBy`](#orderBy)
* [`Take`](#take)
* [`Uniq`](#distinct), [`UniqBy`](#distinctBy)
* [`Value`](#value)
* [`Values`](#values)
* [`Where`](#where), [`WhereBy`](#whereBy)

Expand Down Expand Up @@ -526,15 +527,11 @@ __Arguments__
__Examples__

```go
src := []string{ "a", "b" }
var res map[string]string
Chain(src).Index(func (r string, _ int) string {
return r
src := []string{"a", "b"}
res := make(map[string]string)
Chain(src).Index(func(item string, _ int) string {
return item
}).Value(&res)
// or
res := Index(src, func (r string, _ int) string {
return r
}).(map[string]string)
// res = map[a:a b:b]
```

Expand All @@ -555,10 +552,8 @@ arr := []testModel{
{ID: 3, Name: "b"},
{ID: 4, Name: "b"},
}
var res map[int]testModel
res := make(map[string]testModel)
Chain(arr).IndexBy("id").Value(&res)
// or
res := IndexBy(arr, "id").(map[int]testModel)
// res = map[1:{{0} 1 a} 2:{{0} 2 a} 3:{{0} 3 b} 4:{{0} 4 b}]
```

Expand Down Expand Up @@ -987,6 +982,43 @@ Chain(src).Take(1).Value(&dst)
// res = [1]
```

<a name="value" />

### Value(res interface{})

__Arguments__

* `res` - array or slice or reflect.Value(array) or reflect.Value(map)

__Examples__

```go
resValue := reflect.New(
reflect.SliceOf(
reflect.TypeOf(1),
),
)
Chain([]string{"a", "b"}).Map(func(_ string, i int) int {
return i
}).Value(resValue)
// resValue = &[0 1]

src := []testModel{
{ID: 1, Name: "a"},
{ID: 2, Name: "a"},
{ID: 3, Name: "b"},
{ID: 4, Name: "b"},
}
resValue := reflect.New(
reflect.MapOf(
reflect.TypeOf(src[0].Name),
reflect.TypeOf(src),
),
)
Chain(src).GroupBy("name").Value(resValue)
// res = &map[even:[2 4] odd:[1 3 5]]
```

<a name="values" />

### Values() IEnumerable
Expand Down
48 changes: 25 additions & 23 deletions aggregate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,32 @@ import (
)

func Benchmark_Aggregate(b *testing.B) {
for n := 0; n < b.N; n++ {
total := 0
Range(1, 100, 1).Aggregate(
func(memo []int, r, _ int) []int {
memo = append(memo, r)
memo = append(memo, -r)
return memo
},
make([]int, 0),
).Value(&total)
}
}
b.Run("default", func(b *testing.B) {
for n := 0; n < b.N; n++ {
total := 0
Range(1, 100, 1).Aggregate(
func(memo []int, r, _ int) []int {
memo = append(memo, r)
memo = append(memo, -r)
return memo
},
make([]int, 0),
).Value(&total)
}
})

func Benchmark_Aggregate_NoValue(b *testing.B) {
for n := 0; n < b.N; n++ {
Range(1, 100, 1).Aggregate(
func(memo []int, r, _ int) []int {
memo = append(memo, r)
memo = append(memo, -r)
return memo
},
make([]int, 0),
)
}
b.Run("no value", func(b *testing.B) {
for n := 0; n < b.N; n++ {
Range(1, 100, 1).Aggregate(
func(memo []int, r, _ int) []int {
memo = append(memo, r)
memo = append(memo, -r)
return memo
},
make([]int, 0),
)
}
})
}

func Test_Aggregate(t *testing.T) {
Expand Down
4 changes: 3 additions & 1 deletion group.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package underscore

import "reflect"
import (
"reflect"
)

func (m enumerable) Group(keySelector interface{}) enumerable {
return enumerable{
Expand Down
118 changes: 79 additions & 39 deletions group_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package underscore

import (
"reflect"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -18,51 +19,90 @@ func Benchmark_Group(b *testing.B) {
}
}

func Benchmark_Group_New(b *testing.B) {
for n := 0; n < b.N; n++ {
dst := make([]int, 0)
Range(1, benchmarkSize, 1).Group(func(n, _ int) string {
func Test_Group(t *testing.T) {
t.Run("default", func(t *testing.T) {
res := make(map[string][]int)
Chain([]int{1, 2, 3, 4, 5}).Group(func(n, _ int) string {
if n%2 == 0 {
return "even"
}
return "odd"
}).Value(&dst)
}
}
}).Value(&res)
assert.EqualValues(
t,
res,
map[string][]int{
"odd": {1, 3, 5},
"even": {2, 4},
},
)
})

func Test_Group(t *testing.T) {
res := make(map[string][]int)
Chain([]int{1, 2, 3, 4, 5}).Group(func(n, _ int) string {
if n%2 == 0 {
return "even"
}
return "odd"
}).Value(&res)
assert.EqualValues(
t,
res,
map[string][]int{
"odd": {1, 3, 5},
"even": {2, 4},
},
)
t.Run("reflect.Value", func(t *testing.T) {
resValue := reflect.New(
reflect.MapOf(
reflect.TypeOf(""),
reflect.TypeOf([]int{}),
),
)
Chain([]int{1, 2, 3, 4, 5}).Group(func(n, _ int) string {
if n%2 == 0 {
return "even"
}
return "odd"
}).Value(resValue)
assert.EqualValues(
t,
resValue.Interface(),
map[string][]int{
"odd": {1, 3, 5},
"even": {2, 4},
},
)
})
}

func Test_GroupBy(t *testing.T) {
src := []testModel{
{ID: 1, Name: "a"},
{ID: 2, Name: "a"},
{ID: 3, Name: "b"},
{ID: 4, Name: "b"},
}
res := make(map[string][]testModel)
Chain(src).GroupBy("Name").Value(&res)
assert.EqualValues(
t,
res,
map[string][]testModel{
"a": {src[0], src[1]},
"b": {src[2], src[3]},
},
)
t.Run("default", func(t *testing.T) {
src := []testModel{
{ID: 1, Name: "a"},
{ID: 2, Name: "a"},
{ID: 3, Name: "b"},
{ID: 4, Name: "b"},
}
res := make(map[string][]testModel)
Chain(src).GroupBy("Name").Value(&res)
assert.EqualValues(
t,
res,
map[string][]testModel{
"a": {src[0], src[1]},
"b": {src[2], src[3]},
},
)
})

t.Run("reflect.Value", func(t *testing.T) {
src := []testModel{
{ID: 1, Name: "a"},
{ID: 2, Name: "a"},
{ID: 3, Name: "b"},
{ID: 4, Name: "b"},
}
res := reflect.New(
reflect.MapOf(
reflect.TypeOf(src[0].Name),
reflect.TypeOf(src),
),
)
Chain(src).GroupBy("name").Value(res)
assert.EqualValues(
t,
res.Elem().Interface(),
map[string][]testModel{
"a": {src[0], src[1]},
"b": {src[2], src[3]},
},
)
})
}
25 changes: 23 additions & 2 deletions map_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package underscore

import (
"fmt"
"reflect"
"strconv"
"testing"

"github.com/stretchr/testify/assert"
)

func Test_Map(t *testing.T) {
t.Run("ok", func(t *testing.T) {
t.Run("default", func(t *testing.T) {
src := []string{"11", "12", "13"}
var res []int
Chain(src).Map(func(s string, _ int) int {
Expand All @@ -22,7 +24,7 @@ func Test_Map(t *testing.T) {
)
})

t.Run("ptr", func(t *testing.T) {
t.Run("元素是指针", func(t *testing.T) {
src := []string{"11", "12", "13"}
var res []*string
Chain(src).Map(func(r string, _ int) *string {
Expand All @@ -34,6 +36,25 @@ func Test_Map(t *testing.T) {
[]*string{&src[0], &src[1], &src[2]},
)
})

t.Run("结果为reflect.Value", func(t *testing.T) {
resValue := reflect.New(
reflect.SliceOf(
reflect.TypeOf(1),
),
)
Chain([]string{"a", "b"}).Map(func(_ string, i int) int {
return i
}).Value(resValue)
assert.EqualValues(
t,
resValue.Elem().Interface(),
[]int{0, 1},
)
fmt.Println(resValue)

assert.True(t, false)
})
}

func Test_MapBy(t *testing.T) {
Expand Down
15 changes: 12 additions & 3 deletions value.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package underscore

import "reflect"
import (
"reflect"
)

func (m enumerable) Value(res interface{}) {
resValue := reflect.ValueOf(res)
var resValue reflect.Value
var ok bool
if resValue, ok = res.(reflect.Value); !ok {
resValue = reflect.ValueOf(res)
}

switch resValue.Elem().Kind() {
case reflect.Array, reflect.Slice:
m.valueToArrayOrSlice(resValue)
Expand Down Expand Up @@ -33,7 +40,9 @@ func (m enumerable) valueToArrayOrSlice(resValue reflect.Value) {

func (m enumerable) valueToMap(resValue reflect.Value) {
iterator := m.GetEnumerator()
mapValue := resValue.Elem()
mapValue := reflect.MakeMap(
resValue.Elem().Type(),
)
for ok := iterator.MoveNext(); ok; ok = iterator.MoveNext() {
mapValue.SetMapIndex(
iterator.GetKey(),
Expand Down

0 comments on commit 2827f6b

Please sign in to comment.