-
Notifications
You must be signed in to change notification settings - Fork 1
/
slide.go
65 lines (52 loc) · 1.6 KB
/
slide.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
package ranges
type slideResult[T any] struct {
r ForwardRange[T]
windowSize int
stepSize int
}
func (sr *slideResult[T]) Empty() bool {
return sr.r.Empty()
}
func (sr *slideResult[T]) Front() ForwardRange[T] {
return TakeF(sr.r.Save(), sr.windowSize)
}
func (sr *slideResult[T]) PopFront() {
for i := 0; i < sr.stepSize && !sr.r.Empty(); i++ {
sr.r.PopFront()
}
// Check if there's a remaining window of the given size.
if !sr.r.Empty() {
r := sr.r.Save()
r.PopFront()
for i := sr.stepSize + 1; i < sr.windowSize && !r.Empty(); i++ {
r.PopFront()
}
if r.Empty() {
sr.r = r
}
}
}
func (sr *slideResult[T]) Save() ForwardRange[ForwardRange[T]] {
return &slideResult[T]{sr.r.Save(), sr.windowSize, sr.stepSize}
}
// Slide yields chunks starting from every element in a range.
//
// This function will panic `if windowSize < 1`.
func Slide[T any](r ForwardRange[T], windowSize int) ForwardRange[ForwardRange[T]] {
return SlideStep(r, windowSize, 1)
}
// SlideS is `Slide` accepting a slice.
func SlideS[T any](r []T, windowSize int) ForwardRange[ForwardRange[T]] {
return SlideStepS(r, windowSize, 1)
}
// SlideStep is `Slide` steping over elements with a given `stepSize`
func SlideStep[T any](r ForwardRange[T], windowSize int, stepSize int) ForwardRange[ForwardRange[T]] {
if windowSize < 1 {
panic("windowSize < 1 for Slide")
}
return &slideResult[T]{r, windowSize, stepSize}
}
// SlideStepS is `Slide` accepting a slice.
func SlideStepS[T any](r []T, windowSize int, stepSize int) ForwardRange[ForwardRange[T]] {
return SlideStep(SliceRange(r), windowSize, stepSize)
}