forked from ahmetb/go-linq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
take.go
129 lines (109 loc) · 2.8 KB
/
take.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package linq
// Take returns a specified number of contiguous elements from the start of a
// collection.
func (q Query) Take(count int) Query {
return Query{
Iterate: func() Iterator {
next := q.Iterate()
n := count
return func() (item interface{}, ok bool) {
if n <= 0 {
return
}
n--
return next()
}
},
}
}
// TakeWhile returns elements from a collection as long as a specified condition
// is true, and then skips the remaining elements.
func (q Query) TakeWhile(predicate func(interface{}) bool) Query {
return Query{
Iterate: func() Iterator {
next := q.Iterate()
done := false
return func() (item interface{}, ok bool) {
if done {
return
}
item, ok = next()
if !ok {
done = true
return
}
if predicate(item) {
return
}
done = true
return nil, false
}
},
}
}
// TakeWhileT is the typed version of TakeWhile.
//
// - predicateFn is of type "func(TSource)bool"
//
// NOTE: TakeWhile has better performance than TakeWhileT.
func (q Query) TakeWhileT(predicateFn interface{}) Query {
predicateGenericFunc, err := newGenericFunc(
"TakeWhileT", "predicateFn", predicateFn,
simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(bool))),
)
if err != nil {
panic(err)
}
predicateFunc := func(item interface{}) bool {
return predicateGenericFunc.Call(item).(bool)
}
return q.TakeWhile(predicateFunc)
}
// TakeWhileIndexed returns elements from a collection as long as a specified
// condition is true. The element's index is used in the logic of the predicate
// function. The first argument of predicate represents the zero-based index of
// the element within collection. The second argument represents the element to
// test.
func (q Query) TakeWhileIndexed(predicate func(int, interface{}) bool) Query {
return Query{
Iterate: func() Iterator {
next := q.Iterate()
done := false
index := 0
return func() (item interface{}, ok bool) {
if done {
return
}
item, ok = next()
if !ok {
done = true
return
}
if predicate(index, item) {
index++
return
}
done = true
return nil, false
}
},
}
}
// TakeWhileIndexedT is the typed version of TakeWhileIndexed.
//
// - predicateFn is of type "func(int,TSource)bool"
//
// NOTE: TakeWhileIndexed has better performance than TakeWhileIndexedT.
func (q Query) TakeWhileIndexedT(predicateFn interface{}) Query {
whereFunc, err := newGenericFunc(
"TakeWhileIndexedT", "predicateFn", predicateFn,
simpleParamValidator(newElemTypeSlice(new(int), new(genericType)), newElemTypeSlice(new(bool))),
)
if err != nil {
panic(err)
}
predicateFunc := func(index int, item interface{}) bool {
return whereFunc.Call(index, item).(bool)
}
return q.TakeWhileIndexed(predicateFunc)
}