Skip to content

Commit

Permalink
Reduce、Take支持IEnumerable
Browse files Browse the repository at this point in the history
IEnumerable增加Aggregate、Skip
IQuery删除Clone
优化IEnumerable的First、Index、Values
  • Loading branch information
ahl5esoft committed Jun 15, 2019
1 parent e31e24d commit 6f2dbcf
Show file tree
Hide file tree
Showing 18 changed files with 292 additions and 257 deletions.
128 changes: 60 additions & 68 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-1.2.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-1.4.0-green.svg)
like <a href="http://underscorejs.org/">underscore.js</a>, but for Go

## Installation
Expand All @@ -24,11 +24,11 @@ like <a href="http://underscorejs.org/">underscore.js</a>, but for Go
## Documentation

### API
* [`Aggregate`](#aggregate)
* [`All`](#all), [`AllBy`](#allBy)
* [`Any`](#any), [`AnyBy`](#anyBy)
* [`AsParallel`](#asParallel)
* [`Chain`](#chain)
* [`Clone`](#clone)
* [`Distinct`](#distinct), [`DistinctBy`](#distinctBy)
* [`Each`](#each)
* [`Filter`](#where), [`FilterBy`](#whereBy)
Expand All @@ -46,17 +46,44 @@ like <a href="http://underscorejs.org/">underscore.js</a>, but for Go
* [`Object`](#object)
* [`Property`](#property), [`PropertyRV`](#propertyRV)
* [`Range`](#range)
* [`Reduce`](#reduce)
* [`Reduce`](#aggregate)
* [`Reject`](#reject), [`RejectBy`](#rejectBy)
* [`Reverse`](#reverse), [`ReverseBy`](#reverseBy)
* [`Select`](#select), [`SelectBy`](#selectBy)
* [`Size`](#size)
* [`Skip`](#skip)
* [`Sort`](#sort), [`SortBy`](#sortBy)
* [`Take`](#take)
* [`Uniq`](#distinct), [`UniqBy`](#distinctBy)
* [`Values`](#values)
* [`Where`](#where), [`WhereBy`](#whereBy)

<a name="aggregate" />

### Aggregate(memo, fn) IEnumerable
### Aggregate(source, iterator) IQuery

__Arguments__

* `memo` - anyType
* `iterator` - func(memo, element or value, key or index) memo

__Examples__

```go
dst := make([]int, 0)
Chain2([]int{1, 2}).Aggregate(make([]int, 0), func(memo []int, n, _ int) []int {
memo = append(memo, n)
memo = append(memo, n+10)
return memo
}).Value(&dst)
// dst = [1 11 2 12]
```

__Same__

* `Reduce`

<a name="all" />

### All(predicate) bool
Expand Down Expand Up @@ -200,28 +227,6 @@ Chain([]int{1, 2, 1, 4, 1, 3}).Uniq(nil).Group(func(n, _ int) string {
// len(res) == 2 && ok == true
```

<a name="clone" />

### Clone()

__Return__

* interface{}

__Examples__

```go
arr := []int{1, 2, 3}
var duplicate []int
Chain(arr).Clone().Value(&duplicate)
// or
duplicate := Clone(arr)
ok := All(duplicate, func(n, i int) bool {
return arr[i] == n
})
// ok == true
```

<a name="distinct" />

### Distinct(selector) IEnumerable
Expand Down Expand Up @@ -842,38 +847,6 @@ Range2(0, 3, 2).Value(&res)
// res = [0 2]
```

<a name="reduce" />

### Reduce(source, iterator)

__Arguments__

* `source` - array
* `iterator` - func(memo, element or value, key or index) memo
* `memo` - anyType

__Return__

* interface{} - memo

__Examples__

```go
var res []int
Chain([]int{1, 2}).Reduce(func(memo []int, n, _ int) []int {
memo = append(memo, n)
memo = append(memo, n+10)
return memo
}, make([]int, 0)).Value(&res)
// or
res := Reduce([]int{1, 2}, func(memo []int, n, _ int) []int {
memo = append(memo, n)
memo = append(memo, n+10)
return memo
}, make([]int, 0)).([]int)
// res = [1 11 2 12]
```

<a name="reject" />

### Reject(source, predicate)
Expand Down Expand Up @@ -1067,6 +1040,23 @@ l := Size(dict)
// l = 3
```

<a name="skip" />

### Skip(count) IEnumerable

__Arguments__

* `count` - int

__Examples__

```go
src := []int{1, 2, 3}
dst := make([]int, 0)
Chain2(src).Skip(2).Value(&dst)
// dst = [3]
```

<a name="sort" />

### Sort(source, selector)
Expand Down Expand Up @@ -1129,25 +1119,19 @@ res := SortBy(arr, "id").([]testModel)

<a name="take" />

### Take(source, count)
### Take(count) IEnumerable
### Take(count) IQuery

__Arguments__

* `source` - array or map
* `count` - int

__Return__

* interface{}

__Examples__

```go
arr := []int{1, 2, 3}
var res []int
Chain(arr).Take(1).Value(&res)
// or
res := Take(arr, 1).([]int)
src := []int{1, 2, 3}
dst := make([]int, 0)
Chain2(src).Take(1).Value(&dst)
// res = [1]
```

Expand Down Expand Up @@ -1234,6 +1218,14 @@ __Same__
* `FilterBy`

## Release Notes
~~~
v1.4.0 (2019-06-15)
* Reduce、Take支持IEnumerable
* IEnumerable增加Aggregate、Skip
* IQuery删除Clone
* 优化IEnumerable的First、Index、Values
~~~

~~~
v1.3.0 (2019-06-09)
* FindIndex、FindIndexBy、Keys、Map、MapBy、Object、Uniq、UniqBy、Values支持IEnumerable
Expand Down
17 changes: 17 additions & 0 deletions aggregate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package underscore

import "reflect"

func (m enumerable) Aggregate(memo interface{}, fn interface{}) IEnumerable {
fnRV := reflect.ValueOf(fn)
iterator := m.GetEnumerator()
memoRV := reflect.ValueOf(memo)
for ok := iterator.MoveNext(); ok; ok = iterator.MoveNext() {
memoRV = fnRV.Call([]reflect.Value{
memoRV,
iterator.GetValue(),
iterator.GetKey(),
})[0]
}
return chainFromRV(memoRV)
}
38 changes: 38 additions & 0 deletions aggregate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package underscore

import (
"testing"
)

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

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

func Test_Aggregate(t *testing.T) {
dst := make([]int, 0)
Chain2([]int{1, 2}).Aggregate(make([]int, 0), func(memo []int, n, _ int) []int {
memo = append(memo, n)
memo = append(memo, n+10)
return memo
}).Value(&dst)
if !(len(dst) == 4 && dst[0] == 1 && dst[1] == 11 && dst[2] == 2 && dst[3] == 12) {
t.Error(dst)
}
}
55 changes: 30 additions & 25 deletions chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,12 @@ func Chain(source interface{}) IQuery {

// Chain2 is 初始化
func Chain2(src interface{}) IEnumerable {
srcRV := reflect.ValueOf(src)
switch srcRV.Kind() {
case reflect.Array, reflect.Slice:
return chainByArrayOrSlice(srcRV, srcRV.Len())
case reflect.Map:
return chainByMap(srcRV, srcRV.Len())
default:
if iterator, ok := src.(IEnumerator); ok {
return enumerable{
Enumerator: func() IEnumerator {
return iterator
},
}
}

return enumerable{
Enumerator: func() IEnumerator {
return nullEnumerator{
Src: srcRV,
}
},
}
}
return chainFromRV(
reflect.ValueOf(src),
)
}

func chainByArrayOrSlice(srcRV reflect.Value, size int) IEnumerable {
func chainFromArrayOrSlice(srcRV reflect.Value, size int) IEnumerable {
return enumerable{
Enumerator: func() IEnumerator {
index := 0
Expand All @@ -56,7 +36,7 @@ func chainByArrayOrSlice(srcRV reflect.Value, size int) IEnumerable {
}
}

func chainByMap(srcRV reflect.Value, size int) IEnumerable {
func chainFromMap(srcRV reflect.Value, size int) IEnumerable {
return enumerable{
Enumerator: func() IEnumerator {
index := 0
Expand All @@ -76,3 +56,28 @@ func chainByMap(srcRV reflect.Value, size int) IEnumerable {
},
}
}

func chainFromRV(rv reflect.Value) IEnumerable {
switch rv.Kind() {
case reflect.Array, reflect.Slice:
return chainFromArrayOrSlice(rv, rv.Len())
case reflect.Map:
return chainFromMap(rv, rv.Len())
default:
if iterator, ok := rv.Interface().(IEnumerator); ok {
return enumerable{
Enumerator: func() IEnumerator {
return iterator
},
}
}

return enumerable{
Enumerator: func() IEnumerator {
return nullEnumerator{
Src: rv,
}
},
}
}
}
33 changes: 0 additions & 33 deletions clone.go

This file was deleted.

Loading

0 comments on commit 6f2dbcf

Please sign in to comment.