flabk/pkg/coll/vector.go

139 lines
2.5 KiB
Go
Raw Permalink Normal View History

2022-08-02 13:18:08 +01:00
package coll
import "fmt"
const (
DefaultSize = 4
)
2022-08-02 15:49:10 +01:00
type Vector[T any] []T
2022-08-02 13:18:08 +01:00
func New[T any]() Vector[T] {
return WithCap[T](DefaultSize)
}
func WithCap[T any](capacity int) Vector[T] {
2022-08-02 15:49:10 +01:00
return make(Vector[T], 0, capacity)
2022-08-02 13:18:08 +01:00
}
func From[T any](v ...T) Vector[T] {
2022-08-02 15:49:10 +01:00
return Vector[T](v)
2022-08-02 13:18:08 +01:00
}
func (v Vector[T]) Push(t T) Vector[T] {
2022-08-02 15:49:10 +01:00
if len(v) == cap(v) {
2022-08-02 13:18:08 +01:00
v = v.upsize()
}
2022-08-02 15:49:10 +01:00
v = v[:len(v)+1]
v[len(v)-1] = t
2022-08-02 13:18:08 +01:00
return v
}
func (v Vector[T]) Append(t ...T) Vector[T] {
2022-08-02 15:49:10 +01:00
if cap(v)-len(v) < len(t) {
2022-08-02 13:18:08 +01:00
v = v.upsizeSpecific(len(t))
}
2022-08-02 15:49:10 +01:00
startLen := len(v)
v = v[:len(v)+len(t)]
2022-08-02 13:18:08 +01:00
var tIndex int
2022-08-02 15:49:10 +01:00
for index := startLen; index < cap(v); index++ {
v[index] = t[tIndex]
2022-08-02 13:18:08 +01:00
tIndex++
}
return v
}
func (v Vector[T]) Remove(index int) Vector[T] {
return From(append(v[:index], v[index+1:]...)...)
2022-08-02 13:18:08 +01:00
}
// Faster remove function that can be used on vectors where ordering doesn't matter
func (v Vector[T]) RemoveUnordered(index int) Vector[T] {
2022-08-02 15:49:10 +01:00
v[index] = v[len(v)-1]
return v[:len(v)-1]
2022-08-02 13:18:08 +01:00
}
func (v Vector[T]) upsize() Vector[T] {
2022-08-02 15:49:10 +01:00
return v.upsizeSpecific(cap(v))
2022-08-02 13:18:08 +01:00
}
func (v Vector[T]) upsizeSpecific(extraSize int) Vector[T] {
2022-08-02 15:49:10 +01:00
resized := make([]T, len(v), cap(v)+extraSize)
copy(resized, v)
return resized
2022-08-02 13:18:08 +01:00
}
func (v Vector[T]) panicIndex(index int) {
min := -1
2022-08-02 15:49:10 +01:00
if len(v) != 0 {
2022-08-02 13:18:08 +01:00
min = 0
}
2022-08-02 15:49:10 +01:00
panic(fmt.Sprintf("index %d out of range [%d;%d)", index, min, len(v)))
2022-08-02 13:18:08 +01:00
}
// GetSoft tries to get the requested index, or returns a default value if
// it's out of range
func (v Vector[T]) GetSoft(index int) T {
var result T
2022-08-02 15:49:10 +01:00
if index < 0 || index >= len(v) {
2022-08-02 13:18:08 +01:00
return result
}
2022-08-02 15:49:10 +01:00
return v[index]
2022-08-02 13:18:08 +01:00
}
func (v Vector[T]) Get(index int) T {
2022-08-02 15:49:10 +01:00
if index < 0 || index >= len(v) {
2022-08-02 13:18:08 +01:00
v.panicIndex(index)
}
2022-08-02 15:49:10 +01:00
return v[index]
2022-08-02 13:18:08 +01:00
}
func (v Vector[T]) Set(index int, value T) Vector[T] {
2022-08-02 15:49:10 +01:00
if index < 0 || index >= len(v) {
2022-08-02 13:18:08 +01:00
v.panicIndex(index)
}
2022-08-02 15:49:10 +01:00
v[index] = value
2022-08-02 13:18:08 +01:00
return v
}
func (v Vector[T]) Pop() (T, Vector[T]) {
2022-08-02 15:49:10 +01:00
t := v[len(v)-1]
return t, v[:len(v)-1]
2022-08-02 13:18:08 +01:00
}
func (v Vector[T]) Sub(start, end int) Vector[T] {
2022-08-02 15:49:10 +01:00
if start >= len(v) {
2022-08-02 13:18:08 +01:00
v.panicIndex(start)
}
2022-08-02 15:49:10 +01:00
if end >= len(v) {
2022-08-02 13:18:08 +01:00
v.panicIndex(end)
}
if start < 0 {
return From(v[:end]...)
2022-08-02 13:18:08 +01:00
}
if end < 0 {
return From(v[start:]...)
2022-08-02 13:18:08 +01:00
}
return From(v[start:end]...)
2022-08-02 13:18:08 +01:00
}
func (v Vector[T]) Filter(f func(T) bool) Vector[T] {
return Filter(v, f)
}
func (v Vector[T]) Any(f func(T) bool) bool {
return Any(v, f)
}
func (v Vector[T]) Take(howMany int) Vector[T] {
return Take(v, howMany)
}
func (v Vector[T]) Clone() Vector[T] {
2022-08-02 15:49:10 +01:00
clone := make([]T, len(v))
copy(clone, v)
v = clone
2022-08-02 13:18:08 +01:00
return v
}