166 lines
2.9 KiB
Go
166 lines
2.9 KiB
Go
package coll
|
|
|
|
import "fmt"
|
|
|
|
const (
|
|
DefaultSize = 4
|
|
)
|
|
|
|
type Vector[T any] struct {
|
|
array []T
|
|
length int
|
|
capacity int
|
|
}
|
|
|
|
func New[T any]() Vector[T] {
|
|
return WithCap[T](DefaultSize)
|
|
}
|
|
|
|
func WithCap[T any](capacity int) Vector[T] {
|
|
return Vector[T]{
|
|
array: make([]T, capacity),
|
|
length: 0,
|
|
capacity: capacity,
|
|
}
|
|
}
|
|
|
|
func From[T any](v []T) Vector[T] {
|
|
return Vector[T]{
|
|
array: v,
|
|
length: len(v),
|
|
capacity: len(v),
|
|
}
|
|
}
|
|
|
|
func (v Vector[T]) Push(t T) Vector[T] {
|
|
if v.length == v.capacity {
|
|
v = v.upsize()
|
|
}
|
|
|
|
v.array[v.length] = t
|
|
v.length++
|
|
return v
|
|
}
|
|
|
|
func (v Vector[T]) Append(t ...T) Vector[T] {
|
|
if v.capacity-v.length < len(t) {
|
|
v = v.upsizeSpecific(len(t))
|
|
}
|
|
var tIndex int
|
|
for ; v.length < v.capacity; v.length++ {
|
|
v.array[v.length] = t[tIndex]
|
|
tIndex++
|
|
}
|
|
return v
|
|
}
|
|
|
|
func (v Vector[T]) Remove(index int) Vector[T] {
|
|
return From(append(v.array[:index], v.array[index+1:v.length]...))
|
|
}
|
|
|
|
// Faster remove function that can be used on vectors where ordering doesn't matter
|
|
func (v Vector[T]) RemoveUnordered(index int) Vector[T] {
|
|
v.length--
|
|
v.array[index] = v.array[v.length]
|
|
return v
|
|
}
|
|
|
|
func (v Vector[T]) upsize() Vector[T] {
|
|
return v.upsizeSpecific(v.capacity)
|
|
}
|
|
|
|
func (v Vector[T]) upsizeSpecific(extraSize int) Vector[T] {
|
|
v.array = append(v.array, make([]T, extraSize)...)
|
|
v.capacity = len(v.array)
|
|
return v
|
|
}
|
|
|
|
func (v Vector[T]) Slice() []T {
|
|
if v.length == 0 {
|
|
return []T{}
|
|
}
|
|
return v.array[:v.length]
|
|
}
|
|
|
|
func (v Vector[T]) panicIndex(index int) {
|
|
min := -1
|
|
if v.length != 0 {
|
|
min = 0
|
|
}
|
|
panic(fmt.Sprintf("index %d out of range [%d;%d)", index, min, v.length))
|
|
}
|
|
|
|
// 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
|
|
if index < 0 || index >= v.length {
|
|
return result
|
|
}
|
|
return v.array[index]
|
|
}
|
|
|
|
func (v Vector[T]) Get(index int) T {
|
|
if index < 0 || index >= v.length {
|
|
v.panicIndex(index)
|
|
}
|
|
return v.array[index]
|
|
}
|
|
|
|
func (v Vector[T]) Set(index int, value T) Vector[T] {
|
|
if index < 0 || index >= v.length {
|
|
v.panicIndex(index)
|
|
}
|
|
v.array[index] = value
|
|
return v
|
|
}
|
|
|
|
func (v Vector[T]) Len() int {
|
|
return v.length
|
|
}
|
|
|
|
func (v Vector[T]) Iterate() Iterator[T] {
|
|
return Iterator[T](v)
|
|
}
|
|
|
|
func (v Vector[T]) Pop() (T, Vector[T]) {
|
|
v.length--
|
|
t := v.array[v.length]
|
|
return t, v
|
|
}
|
|
|
|
func (v Vector[T]) Sub(start, end int) Vector[T] {
|
|
if start >= v.length {
|
|
v.panicIndex(start)
|
|
}
|
|
if end >= v.length {
|
|
v.panicIndex(end)
|
|
}
|
|
if start < 0 {
|
|
return From(v.array[:end])
|
|
}
|
|
if end < 0 {
|
|
return From(v.array[start:])
|
|
}
|
|
return From(v.array[start:end])
|
|
}
|
|
|
|
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] {
|
|
clone := make([]T, len(v.array))
|
|
copy(clone, v.array)
|
|
v.array = clone
|
|
return v
|
|
}
|