Skip to content

Commit c5c58fc

Browse files
author
ahl5esoft
committed
refactor
1 parent 9918daf commit c5c58fc

21 files changed

+535
-520
lines changed

README.md

Lines changed: 141 additions & 211 deletions
Large diffs are not rendered by default.

distinct.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package underscore
2+
3+
import "reflect"
4+
5+
func (m enumerable) Distinct(selector interface{}) IEnumerable {
6+
if selector == nil {
7+
selector = func(value, _ interface{}) facade {
8+
return facade{
9+
reflect.ValueOf(value),
10+
}
11+
}
12+
}
13+
14+
return enumerable{
15+
Enumerator: func() IEnumerator {
16+
iterator := m.GetEnumerator()
17+
selectorRV := reflect.ValueOf(selector)
18+
set := make(map[interface{}]bool)
19+
return &enumerator{
20+
MoveNextFunc: func() (valueRV reflect.Value, keyRV reflect.Value, ok bool) {
21+
for ok = iterator.MoveNext(); ok; ok = iterator.MoveNext() {
22+
valueRV = iterator.GetValue()
23+
keyRV = iterator.GetKey()
24+
v := getRV(
25+
selectorRV.Call([]reflect.Value{valueRV, keyRV})[0],
26+
).Interface()
27+
if _, has := set[v]; !has {
28+
set[v] = true
29+
return
30+
}
31+
}
32+
return
33+
},
34+
}
35+
},
36+
}
37+
}
38+
39+
func (m enumerable) DistinctBy(fieldName string) IEnumerable {
40+
getter := PropertyRV(fieldName)
41+
return m.Distinct(func(value, _ interface{}) facade {
42+
return facade{
43+
getter(value),
44+
}
45+
})
46+
}

distinct_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package underscore
2+
3+
import "testing"
4+
5+
func Test_Distinct(t *testing.T) {
6+
src := []int{1, 2, 1, 4, 1, 3}
7+
dst := make([]int, 0)
8+
Chain2(src).Distinct(func(n, _ int) (int, error) {
9+
return n % 2, nil
10+
}).Value(&dst)
11+
if len(dst) != 2 {
12+
t.Error(dst)
13+
}
14+
}
15+
16+
func Test_Distinct_SelectorIsNil(t *testing.T) {
17+
src := []int{1, 2, 1, 4, 1, 3}
18+
dst := make([]int, 0)
19+
Chain2(src).Distinct(nil).Value(&dst)
20+
if len(dst) != 4 {
21+
t.Error(dst)
22+
}
23+
}
24+
25+
func Test_DistinctBy(t *testing.T) {
26+
src := []testModel{
27+
{ID: 1, Name: "a"},
28+
{ID: 2, Name: "a"},
29+
{ID: 3, Name: "a"},
30+
}
31+
dst := make([]testModel, 0)
32+
Chain2(src).DistinctBy("name").Value(&dst)
33+
if len(dst) != 1 {
34+
t.Error(dst)
35+
}
36+
}

enumerator.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@ func (m enumerator) GetKey() reflect.Value {
1616
}
1717

1818
func (m enumerator) GetValue() reflect.Value {
19-
if m.value.Type() == facadeRT {
20-
return m.value.Interface().(facade).Real
21-
}
22-
23-
return m.value
19+
return getRV(m.value)
2420
}
2521

2622
func (m *enumerator) MoveNext() (ok bool) {

find-index.go

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
package underscore
22

3-
import (
4-
"reflect"
5-
)
3+
import "reflect"
64

7-
// FindIndex is 根据断言函数获取下标
8-
func FindIndex(source, predicate interface{}) int {
5+
func (m *query) FindIndex(predicate interface{}) int {
96
index := -1
107

11-
if !IsArray(source) {
8+
if !IsArray(m.Source) {
129
return index
1310
}
1411

15-
each(source, predicate, func(okRV, _, keyRV reflect.Value) bool {
12+
each(m.Source, predicate, func(okRV, _, keyRV reflect.Value) bool {
1613
ok := okRV.Bool()
1714
if ok {
1815
index = int(keyRV.Int())
@@ -23,17 +20,33 @@ func FindIndex(source, predicate interface{}) int {
2320
return index
2421
}
2522

26-
// FindIndexBy is 根据字典获取下标
27-
func FindIndexBy(source interface{}, properties map[string]interface{}) int {
28-
return FindIndex(source, func(item interface{}, _ int) bool {
23+
func (m *query) FindIndexBy(properties map[string]interface{}) int {
24+
return m.FindIndex(func(item interface{}, _ int) bool {
2925
return IsMatch(item, properties)
3026
})
3127
}
3228

33-
func (m *query) FindIndex(predicate interface{}) int {
34-
return FindIndex(m.Source, predicate)
29+
func (m enumerable) FindIndex(predicate interface{}) int {
30+
iterator := m.GetEnumerator()
31+
predicateRV := reflect.ValueOf(predicate)
32+
index := 0
33+
for ok := iterator.MoveNext(); ok; ok = iterator.MoveNext() {
34+
returnRVs := predicateRV.Call([]reflect.Value{
35+
iterator.GetValue(),
36+
iterator.GetKey(),
37+
})
38+
if returnRVs[0].Bool() {
39+
return index
40+
}
41+
42+
index++
43+
}
44+
45+
return -1
3546
}
3647

37-
func (m *query) FindIndexBy(properties map[string]interface{}) int {
38-
return FindIndexBy(m.Source, properties)
48+
func (m enumerable) FindIndexBy(dict map[string]interface{}) int {
49+
return m.FindIndex(func(v, _ interface{}) bool {
50+
return IsMatch(v, dict)
51+
})
3952
}

find-index_test.go

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,47 @@
11
package underscore
22

3-
import (
4-
"testing"
5-
)
3+
import "testing"
64

7-
func Test_FindIndex(t *testing.T) {
8-
arr := []testModel{
9-
{ID: 1, Name: "one"},
10-
{ID: 1, Name: "two"},
11-
{ID: 1, Name: "three"},
12-
}
13-
i := FindIndex(arr, func(r testModel, _ int) bool {
14-
return r.Name == arr[1].Name
15-
})
16-
if i != 1 {
17-
t.Error("wrong")
5+
func Benchmark_FindIndex(b *testing.B) {
6+
for n := 0; n < b.N; n++ {
7+
Range(1, benchmarkSize, 1).FindIndex(func(r, _ int) bool {
8+
return r == 200
9+
})
1810
}
1911
}
2012

21-
func Test_FindIndexBy(t *testing.T) {
22-
arr := []testModel{
23-
{ID: 1, Name: "one"},
24-
{ID: 2, Name: "two"},
25-
{ID: 3, Name: "three"},
26-
}
27-
i := FindIndexBy(arr, map[string]interface{}{
28-
"id": 1,
29-
})
30-
if i != 0 {
31-
t.Error("wrong")
13+
func Benchmark_FindIndex_New(b *testing.B) {
14+
for n := 0; n < b.N; n++ {
15+
Range2(1, benchmarkSize, 1).FindIndex(func(r, _ int) bool {
16+
return r == 200
17+
})
3218
}
3319
}
3420

35-
func Test_Chain_FindIndex(t *testing.T) {
36-
arr := []testModel{
21+
func Test_FindIndex(t *testing.T) {
22+
src := []testModel{
3723
{ID: 1, Name: "one"},
3824
{ID: 2, Name: "two"},
3925
{ID: 3, Name: "three"},
4026
}
41-
index := Chain(arr).FindIndex(func(r testModel, _ int) bool {
42-
return r.Name == arr[1].Name
27+
index := Chain2(src).FindIndex(func(r testModel, _ int) bool {
28+
return r.Name == src[1].Name
4329
})
4430
if index != 1 {
4531
t.Error("wrong")
4632
}
4733
}
4834

49-
func Test_Chain_FindIndexBy(t *testing.T) {
50-
arr := []testModel{
35+
func Test_FindIndexBy(t *testing.T) {
36+
src := []testModel{
5137
{ID: 1, Name: "one"},
5238
{ID: 2, Name: "two"},
5339
{ID: 3, Name: "three"},
5440
}
55-
index := Chain(arr).FindIndexBy(map[string]interface{}{
41+
index := Chain2(src).FindIndexBy(map[string]interface{}{
5642
"id": 1,
5743
})
58-
if index == -1 || arr[index].ID != 1 {
44+
if index == -1 || src[index].ID != 1 {
5945
t.Error("wrong")
6046
}
6147
}

i-enumerable.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,27 @@ type IEnumerable interface {
66
AllBy(dict map[string]interface{}) bool
77
Any(predicate interface{}) bool
88
AnyBy(dict map[string]interface{}) bool
9+
Distinct(selector interface{}) IEnumerable
10+
DistinctBy(fieldName string) IEnumerable
911
Each(action interface{})
1012
Filter(predicate interface{}) IEnumerable
1113
FilterBy(dict map[string]interface{}) IEnumerable
1214
Find(predicate interface{}) IEnumerable
1315
FindBy(dict map[string]interface{}) IEnumerable
16+
FindIndex(predicate interface{}) int
17+
FindIndexBy(dict map[string]interface{}) int
1418
First() IEnumerable
1519
GetEnumerator() IEnumerator
20+
Keys() IEnumerable
21+
Map(selector interface{}) IEnumerable
22+
MapBy(fieldName string) IEnumerable
23+
Object() IEnumerable
24+
Select(selector interface{}) IEnumerable
25+
SelectBy(fieldName string) IEnumerable
26+
Uniq(selector interface{}) IEnumerable
27+
UniqBy(fieldName string) IEnumerable
1628
Value(res interface{})
29+
Values() IEnumerable
1730
Where(predicate interface{}) IEnumerable
1831
WhereBy(dict map[string]interface{}) IEnumerable
1932
}

keys.go

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,30 @@
11
package underscore
22

3-
import (
4-
"reflect"
5-
)
3+
import "reflect"
64

7-
// Keys is 获取map的所有key
8-
func Keys(source interface{}) interface{} {
9-
sourceRV := reflect.ValueOf(source)
10-
if sourceRV.Kind() != reflect.Map {
11-
return nil
12-
}
13-
return Map(source, func(_, key interface{}) facade {
5+
func (m *query) Keys() IQuery {
6+
m.Source = m.Map(func(_, key interface{}) facade {
147
return facade{reflect.ValueOf(key)}
158
})
9+
return m
1610
}
1711

18-
func (m *query) Keys() IQuery {
19-
m.Source = Keys(m.Source)
20-
return m
12+
func (m enumerable) Keys() IEnumerable {
13+
return enumerable{
14+
Enumerator: func() IEnumerator {
15+
index := 0
16+
iterator := m.GetEnumerator()
17+
return &enumerator{
18+
MoveNextFunc: func() (valueRV reflect.Value, keyRV reflect.Value, ok bool) {
19+
if ok = iterator.MoveNext(); ok {
20+
valueRV = iterator.GetKey()
21+
keyRV = reflect.ValueOf(index)
22+
index++
23+
}
24+
25+
return
26+
},
27+
}
28+
},
29+
}
2130
}

keys_test.go

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,30 @@
11
package underscore
22

3-
import (
4-
"testing"
5-
)
3+
import "testing"
64

75
func Test_Keys_Array(t *testing.T) {
8-
arr := []string{"aa"}
9-
res := Keys(arr)
10-
if res != nil {
11-
t.Error(res)
6+
src := []string{"aa", "bb", "cc"}
7+
dst := make([]int, 0)
8+
Chain2(src).Keys().Value(&dst)
9+
if len(dst) != len(src) {
10+
t.Fatal(dst)
1211
}
13-
}
14-
15-
func Test_Keys_Hash(t *testing.T) {
16-
dict := map[int]string{
17-
1: "a",
18-
2: "b",
19-
3: "c",
20-
4: "d",
21-
}
22-
res := Keys(dict).([]int)
23-
if len(res) != len(dict) {
24-
t.Error(res)
25-
}
26-
}
2712

28-
func Test_Chain_Keys_Array(t *testing.T) {
29-
arr := []string{"aa"}
30-
res := make([]string, 0)
31-
Chain(arr).Keys().Value(&res)
32-
if len(res) != 0 {
33-
t.Error(res)
13+
if dst[0] != 0 {
14+
t.Error(dst)
3415
}
3516
}
3617

37-
func Test_Chain_Keys_Hash(t *testing.T) {
38-
dict := map[int]string{
18+
func Test_Keys_Map(t *testing.T) {
19+
src := map[int]string{
3920
1: "a",
4021
2: "b",
4122
3: "c",
4223
4: "d",
4324
}
44-
res := make([]int, 0)
45-
Chain(dict).Keys().Value(&res)
46-
if len(res) != len(dict) {
47-
t.Error("wrong")
25+
dst := make([]int, 0)
26+
Chain2(src).Keys().Value(&dst)
27+
if len(dst) != len(src) {
28+
t.Fatal(dst)
4829
}
4930
}

map.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,11 @@ func (m *query) MapBy(property string) IQuery {
4242
m.Source = MapBy(m.Source, property)
4343
return m
4444
}
45+
46+
func (m enumerable) Map(selector interface{}) IEnumerable {
47+
return m.Select(selector)
48+
}
49+
50+
func (m enumerable) MapBy(fieldName string) IEnumerable {
51+
return m.SelectBy(fieldName)
52+
}

0 commit comments

Comments
 (0)