diff --git a/README.md b/README.md
index 590955a..76cbed7 100644
--- a/README.md
+++ b/README.md
@@ -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 underscore.js and C# LINQ, but for Go
## Installation
@@ -57,6 +57,7 @@ like underscore.js and C# LINQ, but for G
* [`Sort`](#order), [`SortBy`](#orderBy)
* [`Take`](#take)
* [`Uniq`](#distinct), [`UniqBy`](#distinctBy)
+* [`Value`](#value)
* [`Values`](#values)
* [`Where`](#where), [`WhereBy`](#whereBy)
@@ -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]
```
@@ -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}]
```
@@ -987,6 +982,43 @@ Chain(src).Take(1).Value(&dst)
// res = [1]
```
+
+
+### 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]]
+```
+
### Values() IEnumerable
diff --git a/aggregate_test.go b/aggregate_test.go
index d3366ce..a37009a 100644
--- a/aggregate_test.go
+++ b/aggregate_test.go
@@ -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) {
diff --git a/group.go b/group.go
index 3674fe7..1e4e640 100644
--- a/group.go
+++ b/group.go
@@ -1,6 +1,8 @@
package underscore
-import "reflect"
+import (
+ "reflect"
+)
func (m enumerable) Group(keySelector interface{}) enumerable {
return enumerable{
diff --git a/group_test.go b/group_test.go
index 8ef4b18..894b852 100644
--- a/group_test.go
+++ b/group_test.go
@@ -1,6 +1,7 @@
package underscore
import (
+ "reflect"
"testing"
"github.com/stretchr/testify/assert"
@@ -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]},
+ },
+ )
+ })
}
diff --git a/map_test.go b/map_test.go
index 13cb632..6085f91 100644
--- a/map_test.go
+++ b/map_test.go
@@ -1,6 +1,8 @@
package underscore
import (
+ "fmt"
+ "reflect"
"strconv"
"testing"
@@ -8,7 +10,7 @@ import (
)
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 {
@@ -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 {
@@ -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) {
diff --git a/value.go b/value.go
index 20c815f..807fef3 100644
--- a/value.go
+++ b/value.go
@@ -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)
@@ -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(),