mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-29 02:30:12 +00:00
* Comment style * IRecordTransformer -> RecordTransfomer * make fmt * else-return style mod * snake-case -> camel-case * Remove redundant err = nil and similar zero-value initializations. * redundant break; * bugfix * neaten * typofix * simplify/standardize init of zero-length slices * Standardize fmt.Fprintf w/ errors * fix double print of "mlr:" * neatening * Uniformize error messages * make docs * avoid shadowing package names * shorten some receiver names
90 lines
2.8 KiB
Go
90 lines
2.8 KiB
Go
// Data structure for mlr top: just a decorated array.
|
|
|
|
package utils
|
|
|
|
import (
|
|
"github.com/johnkerl/miller/v6/pkg/mlrval"
|
|
"github.com/johnkerl/miller/v6/pkg/types"
|
|
)
|
|
|
|
type TopKeeper struct {
|
|
TopValues []*mlrval.Mlrval
|
|
TopRecordsAndContexts []*types.RecordAndContext
|
|
size int64
|
|
capacity int64
|
|
bsearchFunc mlrval.BsearchMlrvalArrayFunc
|
|
}
|
|
|
|
func NewTopKeeper(capacity int64, doMax bool) *TopKeeper {
|
|
keeper := &TopKeeper{
|
|
TopValues: make([]*mlrval.Mlrval, capacity),
|
|
TopRecordsAndContexts: make([]*types.RecordAndContext, capacity),
|
|
size: 0,
|
|
capacity: capacity,
|
|
}
|
|
if doMax {
|
|
keeper.bsearchFunc = mlrval.BsearchMlrvalArrayForDescendingInsert
|
|
} else {
|
|
keeper.bsearchFunc = mlrval.BsearchMlrvalArrayForAscendingInsert
|
|
}
|
|
return keeper
|
|
}
|
|
|
|
func (keeper *TopKeeper) GetSize() int64 {
|
|
return keeper.size
|
|
}
|
|
|
|
// Cases:
|
|
// 1. array size < capacity
|
|
// * find destidx
|
|
// * if destidx == size
|
|
// put it there
|
|
// else
|
|
// shift down & insert
|
|
// increment size
|
|
//
|
|
// 2. array size == capacity
|
|
// * find destidx
|
|
// * if destidx == size
|
|
// discard
|
|
// else
|
|
// shift down & insert
|
|
//
|
|
// capacity = 10, size = 6, destidx = 3 capacity = 10, size = 10, destidx = 3
|
|
// [0 #] [0 #] [0 #] [0 #]
|
|
// [1 #] [1 #] [1 #] [1 #]
|
|
// [2 #] [2 #] [2 #] [2 #]
|
|
// [3 #]* [3 X] [3 #]* [3 X]
|
|
// [4 #] [4 #] [4 #] [4 #]
|
|
// [5 #] [5 #] [5 #] [5 #]
|
|
// [6 ] [6 #] [6 #] [6 #]
|
|
// [7 ] [7 ] [7 #] [7 #]
|
|
// [8 ] [8 ] [8 #] [8 #]
|
|
// [9 ] [9 ] [9 #] [9 #]
|
|
//
|
|
// Our caller, the 'top' verb, feeds us records. We keep them or not; in the
|
|
// latter case, the Go runtime GCs them.
|
|
|
|
func (keeper *TopKeeper) Add(value *mlrval.Mlrval, recordAndContext *types.RecordAndContext) {
|
|
destidx := keeper.bsearchFunc(&keeper.TopValues, keeper.size, value)
|
|
|
|
if keeper.size < keeper.capacity {
|
|
for i := keeper.size - 1; i >= destidx; i-- {
|
|
keeper.TopValues[i+1] = keeper.TopValues[i]
|
|
keeper.TopRecordsAndContexts[i+1] = keeper.TopRecordsAndContexts[i]
|
|
}
|
|
keeper.TopValues[destidx] = value.Copy()
|
|
keeper.TopRecordsAndContexts[destidx] = recordAndContext.Copy() // might be nil
|
|
keeper.size++
|
|
} else {
|
|
if destidx >= keeper.capacity {
|
|
return
|
|
}
|
|
for i := keeper.size - 2; i >= destidx; i-- {
|
|
keeper.TopValues[i+1] = keeper.TopValues[i]
|
|
keeper.TopRecordsAndContexts[i+1] = keeper.TopRecordsAndContexts[i]
|
|
}
|
|
keeper.TopValues[destidx] = value.Copy()
|
|
keeper.TopRecordsAndContexts[destidx] = recordAndContext.Copy()
|
|
}
|
|
}
|