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  }