-
Notifications
You must be signed in to change notification settings - Fork 1
/
chunkby.go
68 lines (53 loc) · 1.36 KB
/
chunkby.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
package ranges
func takeChunks[T any](
cr *chunkByResult[T],
takeWhileFunc func(r InputRange[T], cb func(element T) bool) InputRange[T],
) InputRange[T] {
hasLast := false
var last T
cr.takeWhile = takeWhileFunc(cr.r, func(x T) bool {
if !hasLast {
hasLast = true
last = x
return true
}
if cr.cb(last, x) {
last = x
return true
}
return false
})
return cr.takeWhile
}
type chunkByResult[T any] struct {
r InputRange[T]
cb func(a, b T) bool
takeWhile InputRange[T]
}
func (cr *chunkByResult[T]) Empty() bool {
return cr.r.Empty()
}
func (cr *chunkByResult[T]) Front() InputRange[T] {
return takeChunks(cr, TakeWhile[T])
}
func (cr *chunkByResult[T]) PopFront() {
if cr.takeWhile == nil {
cr.Front()
cr.takeWhile.PopFront()
}
Exhaust(cr.takeWhile)
cr.takeWhile = nil
}
type chunkByForwardResult[T any] struct {
r InputRange[T]
cb func(a, b T) bool
takeWhile InputRange[T]
}
// Returns a range that splits a range into subranges when `cb(a, b)` returns `false`.
func ChunkBy[T any](r InputRange[T], cb func(a, b T) bool) InputRange[InputRange[T]] {
return &chunkByResult[T]{r, cb, nil}
}
// Returns `ChunkBy` with `cb(a) == cb(b)`
func ChunkByValue[T any, U comparable](r InputRange[T], cb func(a T) U) InputRange[InputRange[T]] {
return ChunkBy(r, func(a, b T) bool { return cb(a) == cb(b) })
}