github.com/djordje200179/extendedlibrary/datastructures@v1.7.1-0.20240227175559-d09520a92dd4/cols/array/array.go (about) 1 package array 2 3 import ( 4 "github.com/djordje200179/extendedlibrary/datastructures/cols" 5 "github.com/djordje200179/extendedlibrary/datastructures/iter" 6 "github.com/djordje200179/extendedlibrary/misc/functions/comparison" 7 "github.com/djordje200179/extendedlibrary/misc/functions/predication" 8 "slices" 9 ) 10 11 // Array is a collection that stores elements in a contiguous memory block. 12 // The zero value is ready to use. Do not copy a non-zero Array. 13 type Array[T any] struct { 14 slice []T 15 } 16 17 // New creates an empty Array. 18 func New[T any]() *Array[T] { 19 return NewWithSize[T](0) 20 } 21 22 // NewWithSize creates an empty Array with the specified initial size. 23 func NewWithSize[T any](initialSize int) *Array[T] { 24 return FromSlice(make([]T, initialSize)) 25 } 26 27 // NewWithCapacity creates an empty Array with the specified initial capacity. 28 func NewWithCapacity[T any](initialCapacity int) *Array[T] { 29 return FromSlice(make([]T, 0, initialCapacity)) 30 } 31 32 // NewFromIterable creates a new Array from the specified iter.Iterable. 33 func NewFromIterable[T any](iterable iter.Iterable[T]) *Array[T] { 34 var array *Array[T] 35 if finiteIterable, ok := any(iterable).(iter.FiniteIterable[T]); ok { 36 array = NewWithSize[T](finiteIterable.Size()) 37 38 i := 0 39 for it := iterable.Iterator(); it.Valid(); it.Move() { 40 array.slice[i] = it.Get() 41 i++ 42 } 43 } else { 44 array = New[T]() 45 46 for it := iterable.Iterator(); it.Valid(); it.Move() { 47 array.Append(it.Get()) 48 } 49 } 50 51 return array 52 } 53 54 // FromSlice creates a new Array from the specified slice. 55 func FromSlice[T any](slice []T) *Array[T] { 56 return &Array[T]{slice} 57 } 58 59 // Size returns the number of elements in the Array. 60 func (arr *Array[T]) Size() int { 61 return len(arr.slice) 62 } 63 64 // Capacity returns the number of elements that the Array can hold without reallocating. 65 func (arr *Array[T]) Capacity() int { 66 return cap(arr.slice) 67 } 68 69 func (arr *Array[T]) getRealIndex(index int) int { 70 size := arr.Size() 71 72 if index >= size || index < -size { 73 panic(cols.IndexOutOfBoundsError{Index: index, Length: size}) 74 } 75 76 if index < 0 { 77 index += size 78 } 79 80 return index 81 } 82 83 // GetRef returns a reference to the element at the specified index. 84 // Negative indices are interpreted as relative to the end of the Array. 85 // Panics if the index is out of bounds. 86 func (arr *Array[T]) GetRef(index int) *T { 87 index = arr.getRealIndex(index) 88 return &arr.slice[index] 89 } 90 91 // Get returns the element at the specified index. 92 // Negative indices are interpreted as relative to the end of the Array. 93 // Panics if the index is out of bounds. 94 func (arr *Array[T]) Get(index int) T { 95 index = arr.getRealIndex(index) 96 return arr.slice[index] 97 } 98 99 // Set sets the element at the specified index. 100 // Negative indices are interpreted as relative to the end of the Array. 101 // Panics if the index is out of bounds. 102 func (arr *Array[T]) Set(index int, value T) { 103 index = arr.getRealIndex(index) 104 arr.slice[index] = value 105 } 106 107 // Prepend inserts the specified element at the beginning of the Array. 108 func (arr *Array[T]) Prepend(value T) { 109 newArray := make([]T, arr.Size()+1) 110 111 newArray[0] = value 112 copy(newArray[1:], arr.slice) 113 114 arr.slice = newArray 115 } 116 117 // PrependMany inserts the specified elements at the beginning of the Array. 118 func (arr *Array[T]) PrependMany(values ...T) { 119 newArray := make([]T, arr.Size()+len(values)) 120 121 copy(newArray, values) 122 copy(newArray[len(values):], arr.slice) 123 124 arr.slice = newArray 125 } 126 127 // Append appends the specified element to the end of the Array. 128 func (arr *Array[T]) Append(value T) { 129 arr.slice = append(arr.slice, value) 130 } 131 132 // AppendMany appends the specified elements to the end of the Array. 133 func (arr *Array[T]) AppendMany(values ...T) { 134 arr.slice = append(arr.slice, values...) 135 } 136 137 // Insert inserts the specified element at the specified index. 138 // Negative indices are interpreted as relative to the end of the Array. 139 // Panics if the index is out of bounds. 140 func (arr *Array[T]) Insert(index int, value T) { 141 index = arr.getRealIndex(index) 142 143 newArray := make([]T, arr.Size()+1) 144 145 copy(newArray, arr.slice[:index]) 146 newArray[index] = value 147 copy(newArray[index+1:], arr.slice[index:]) 148 149 arr.slice = newArray 150 } 151 152 // InsertMany inserts the specified elements at the specified index. 153 // Negative indices are interpreted as relative to the end of the Array. 154 // Panics if the index is out of bounds. 155 func (arr *Array[T]) InsertMany(index int, values ...T) { 156 index = arr.getRealIndex(index) 157 158 arr.slice = slices.Insert(arr.slice, index, values...) 159 } 160 161 // Remove removes the element at the specified index. 162 // Negative indices are interpreted as relative to the end of the Array. 163 // Panics if the index is out of bounds. 164 func (arr *Array[T]) Remove(index int) { 165 index = arr.getRealIndex(index) 166 167 oldSlice := arr.slice 168 switch { 169 case index == 0: 170 arr.slice = oldSlice[1:] 171 case index == arr.Size()-1: 172 arr.slice = oldSlice[:index] 173 default: 174 arr.slice = append(oldSlice[:index], oldSlice[index+1:]...) 175 } 176 } 177 178 // Reserve reserves additional capacity for the Array. 179 // If additionalCapacity is negative, the function does nothing. 180 func (arr *Array[T]) Reserve(additionalCapacity int) { 181 newCapacity := arr.Capacity() + additionalCapacity 182 183 if newCapacity <= arr.Capacity() { 184 return 185 } 186 187 newSlice := make([]T, arr.Size(), newCapacity) 188 copy(newSlice, arr.slice) 189 arr.slice = newSlice 190 } 191 192 // Shrink shrinks the capacity of the Array to match its size. 193 func (arr *Array[T]) Shrink() { 194 arr.slice = slices.Clip(arr.slice) 195 } 196 197 // Clear removes all elements from the Array. 198 func (arr *Array[T]) Clear() { 199 arr.slice = make([]T, 0) 200 } 201 202 // Reverse reverses the order of the elements in the Array. 203 func (arr *Array[T]) Reverse() { 204 slices.Reverse(arr.slice) 205 } 206 207 // Sort sorts the elements in the Array by the specified comparator. 208 // The sorting algorithm is stable. 209 func (arr *Array[T]) Sort(comparator comparison.Comparator[T]) { 210 slices.SortStableFunc(arr.slice, comparator) 211 } 212 213 // Join appends all elements from the other collection to the Array. 214 // The other collection is cleared. 215 func (arr *Array[T]) Join(other cols.Collection[T]) { 216 switch second := other.(type) { 217 case *Array[T]: 218 arr.AppendMany(second.slice...) 219 default: 220 for it := other.Iterator(); it.Valid(); it.Move() { 221 arr.Append(it.Get()) 222 } 223 } 224 225 other.Clear() 226 } 227 228 // Clone returns a copy of the Array. 229 func (arr *Array[T]) Clone() cols.Collection[T] { 230 return &Array[T]{slices.Clone(arr.slice)} 231 } 232 233 // Iterator returns an iterator over the elements in the Array. 234 func (arr *Array[T]) Iterator() iter.Iterator[T] { 235 return arr.CollectionIterator() 236 } 237 238 // CollectionIterator returns an iterator over the elements in the Array. 239 func (arr *Array[T]) CollectionIterator() cols.Iterator[T] { 240 return &Iterator[T]{arr, 0} 241 } 242 243 // Stream streams elements of the Array. 244 func (arr *Array[T]) Stream(yield func(T) bool) { 245 // TODO: Use slices.Stream 246 for _, val := range arr.slice { 247 if !yield(val) { 248 break 249 } 250 } 251 } 252 253 // RefsStream streams references to the elements in the Array. 254 func (arr *Array[T]) RefsStream(yield func(*T) bool) { 255 for i := range arr.slice { 256 if !yield(&arr.slice[i]) { 257 break 258 } 259 } 260 } 261 262 // FindIndex returns the index of the first element that matches the specified predicate. 263 func (arr *Array[T]) FindIndex(predicate predication.Predicate[T]) (int, bool) { 264 index := slices.IndexFunc(arr.slice, predicate) 265 if index == -1 { 266 return 0, false 267 } 268 269 return index, true 270 } 271 272 // FindRef returns a reference to the first element that matches the specified predicate. 273 func (arr *Array[T]) FindRef(predicate predication.Predicate[T]) (*T, bool) { 274 index, ok := arr.FindIndex(predicate) 275 if !ok { 276 return nil, false 277 } 278 279 return arr.GetRef(index), true 280 } 281 282 // Slice returns a slice of elements in the Array. 283 func (arr *Array[T]) Slice() []T { 284 return arr.slice 285 } 286 287 // SliceRange returns a slice of elements in the Array in the specified range. 288 func (arr *Array[T]) SliceRange(from, to int) []T { 289 from = arr.getRealIndex(from) 290 to = arr.getRealIndex(to) 291 292 return arr.slice[from:to] 293 }