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 }