mirror of
https://github.com/johnkerl/miller.git
synced 2026-08-04 21:43:38 +00:00
window-keeper util class
This commit is contained in:
parent
9a43a1dcd5
commit
cd8b714dc8
3 changed files with 228 additions and 0 deletions
1
.vimrc
1
.vimrc
|
|
@ -1,3 +1,4 @@
|
|||
map \d :w<C-m>:!clear;echo Building ...; echo; make mlr<C-m>
|
||||
map \f :w<C-m>:!clear;echo Building ...; echo; make ut<C-m>
|
||||
map \r :w<C-m>:!clear;echo Building ...; echo; make ut-scan ut-mlv<C-m>
|
||||
map \t :w<C-m>:!clear;go test github.com/johnkerl/miller/internal/pkg/transformers/...<C-m>
|
||||
|
|
|
|||
70
internal/pkg/transformers/utils/window-keeper.go
Normal file
70
internal/pkg/transformers/utils/window-keeper.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"github.com/johnkerl/miller/internal/pkg/lib"
|
||||
)
|
||||
|
||||
// WindowKeeper is a sliding-window container, nominally for use by mlr step,
|
||||
// for holding a number of records before the current one, the current one, and
|
||||
// a number of records after. The payload is interface{}, not *mlrval.Mlrmap,
|
||||
// for ease of unit-testing -- as well as since nothing here inspects the
|
||||
// payload, so this code could be repurposed.
|
||||
type WindowKeeper struct {
|
||||
numBackward int
|
||||
numForward int
|
||||
|
||||
recordsBackward []interface{}
|
||||
currentRecord interface{}
|
||||
recordsForward []interface{}
|
||||
}
|
||||
|
||||
func NewWindowKeeper(
|
||||
numBackward int,
|
||||
numForward int,
|
||||
) *WindowKeeper {
|
||||
return &WindowKeeper{
|
||||
numBackward: numBackward,
|
||||
numForward: numForward,
|
||||
|
||||
recordsBackward: make([]interface{}, numBackward),
|
||||
currentRecord: nil,
|
||||
recordsForward: make([]interface{}, numForward),
|
||||
}
|
||||
}
|
||||
|
||||
func (wk *WindowKeeper) IngestRecord(
|
||||
inrec interface{},
|
||||
) {
|
||||
for i := wk.numBackward - 1; i > 0; i-- {
|
||||
wk.recordsBackward[i] = wk.recordsBackward[i-1]
|
||||
}
|
||||
if wk.numBackward > 0 {
|
||||
wk.recordsBackward[0] = wk.currentRecord
|
||||
}
|
||||
if wk.numForward > 0 {
|
||||
wk.currentRecord = wk.recordsForward[0]
|
||||
for i := 0; i < wk.numForward-1; i++ {
|
||||
wk.recordsForward[i] = wk.recordsForward[i+1]
|
||||
}
|
||||
wk.recordsForward[wk.numForward-1] = inrec
|
||||
} else {
|
||||
wk.currentRecord = inrec
|
||||
}
|
||||
}
|
||||
|
||||
// GetRecord maps a user-visible indexing ..., -3, -2, -1, 0, 1, 2, 3, ...
|
||||
// into this struct's zero-index array storage.
|
||||
func (wk *WindowKeeper) GetRecord(
|
||||
index int,
|
||||
) interface{} {
|
||||
if index == 0 {
|
||||
return wk.currentRecord
|
||||
} else if index > 0 {
|
||||
lib.InternalCodingErrorIf(index > wk.numForward)
|
||||
return wk.recordsForward[index-1]
|
||||
} else {
|
||||
index = -index
|
||||
lib.InternalCodingErrorIf(index > wk.numBackward)
|
||||
return wk.recordsBackward[index-1]
|
||||
}
|
||||
}
|
||||
157
internal/pkg/transformers/utils/window_keeper_test.go
Normal file
157
internal/pkg/transformers/utils/window_keeper_test.go
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test00(t *testing.T) {
|
||||
wk := NewWindowKeeper(0, 0)
|
||||
|
||||
wk.IngestRecord("a")
|
||||
assert.Equal(t, "a", wk.GetRecord(0).(string))
|
||||
|
||||
wk.IngestRecord("b")
|
||||
assert.Equal(t, "b", wk.GetRecord(0).(string))
|
||||
}
|
||||
|
||||
func Test10(t *testing.T) {
|
||||
wk := NewWindowKeeper(1, 0)
|
||||
|
||||
wk.IngestRecord("a")
|
||||
assert.Equal(t, "a", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(-1))
|
||||
|
||||
wk.IngestRecord("b")
|
||||
assert.Equal(t, "b", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(-1).(string))
|
||||
|
||||
wk.IngestRecord("c")
|
||||
assert.Equal(t, "c", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(-1).(string))
|
||||
}
|
||||
|
||||
func Test20(t *testing.T) {
|
||||
wk := NewWindowKeeper(2, 0)
|
||||
|
||||
wk.IngestRecord("a")
|
||||
assert.Equal(t, "a", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(-1))
|
||||
assert.Equal(t, nil, wk.GetRecord(-2))
|
||||
|
||||
wk.IngestRecord("b")
|
||||
assert.Equal(t, "b", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(-1).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(-2))
|
||||
|
||||
wk.IngestRecord("c")
|
||||
assert.Equal(t, "c", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(-1).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(-2).(string))
|
||||
|
||||
wk.IngestRecord("d")
|
||||
assert.Equal(t, "d", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, "c", wk.GetRecord(-1).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(-2).(string))
|
||||
}
|
||||
|
||||
func Test01(t *testing.T) {
|
||||
wk := NewWindowKeeper(0, 1)
|
||||
|
||||
wk.IngestRecord("a")
|
||||
assert.Equal(t, "a", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(0))
|
||||
|
||||
wk.IngestRecord("b")
|
||||
assert.Equal(t, "b", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(0).(string))
|
||||
|
||||
wk.IngestRecord("c")
|
||||
assert.Equal(t, "c", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(0).(string))
|
||||
}
|
||||
|
||||
func Test02(t *testing.T) {
|
||||
wk := NewWindowKeeper(0, 2)
|
||||
|
||||
wk.IngestRecord("a")
|
||||
assert.Equal(t, "a", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(1))
|
||||
assert.Equal(t, nil, wk.GetRecord(0))
|
||||
|
||||
wk.IngestRecord("b")
|
||||
assert.Equal(t, "b", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(0))
|
||||
|
||||
wk.IngestRecord("c")
|
||||
assert.Equal(t, "c", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(0).(string))
|
||||
|
||||
wk.IngestRecord("d")
|
||||
assert.Equal(t, "d", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, "c", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(0).(string))
|
||||
}
|
||||
|
||||
func Test32(t *testing.T) {
|
||||
wk := NewWindowKeeper(3, 2)
|
||||
|
||||
wk.IngestRecord("a")
|
||||
assert.Equal(t, "a", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(1))
|
||||
assert.Equal(t, nil, wk.GetRecord(0))
|
||||
assert.Equal(t, nil, wk.GetRecord(-1))
|
||||
assert.Equal(t, nil, wk.GetRecord(-2))
|
||||
assert.Equal(t, nil, wk.GetRecord(-3))
|
||||
|
||||
wk.IngestRecord("b")
|
||||
assert.Equal(t, "b", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(0))
|
||||
assert.Equal(t, nil, wk.GetRecord(-1))
|
||||
assert.Equal(t, nil, wk.GetRecord(-2))
|
||||
assert.Equal(t, nil, wk.GetRecord(-3))
|
||||
|
||||
wk.IngestRecord("c")
|
||||
assert.Equal(t, "c", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(-1))
|
||||
assert.Equal(t, nil, wk.GetRecord(-2))
|
||||
assert.Equal(t, nil, wk.GetRecord(-3))
|
||||
|
||||
wk.IngestRecord("d")
|
||||
assert.Equal(t, "d", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, "c", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(-1).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(-2))
|
||||
assert.Equal(t, nil, wk.GetRecord(-3))
|
||||
|
||||
wk.IngestRecord("e")
|
||||
assert.Equal(t, "e", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, "d", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, "c", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(-1).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(-2).(string))
|
||||
assert.Equal(t, nil, wk.GetRecord(-3))
|
||||
|
||||
wk.IngestRecord("f")
|
||||
assert.Equal(t, "f", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, "e", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, "d", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, "c", wk.GetRecord(-1).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(-2).(string))
|
||||
assert.Equal(t, "a", wk.GetRecord(-3).(string))
|
||||
|
||||
wk.IngestRecord("g")
|
||||
assert.Equal(t, "g", wk.GetRecord(2).(string))
|
||||
assert.Equal(t, "f", wk.GetRecord(1).(string))
|
||||
assert.Equal(t, "e", wk.GetRecord(0).(string))
|
||||
assert.Equal(t, "d", wk.GetRecord(-1).(string))
|
||||
assert.Equal(t, "c", wk.GetRecord(-2).(string))
|
||||
assert.Equal(t, "b", wk.GetRecord(-3).(string))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue