github.com/alexandrestein/gods@v1.0.1/lists/arraylist/arraylist.go (about) 1 // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package arraylist implements the array list. 6 // 7 // Structure is not thread safe. 8 // 9 // Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29 10 package arraylist 11 12 import ( 13 "fmt" 14 "github.com/alexandrestein/gods/lists" 15 "github.com/alexandrestein/gods/utils" 16 "strings" 17 ) 18 19 func assertListImplementation() { 20 var _ lists.List = (*List)(nil) 21 } 22 23 // List holds the elements in a slice 24 type List struct { 25 elements []interface{} 26 size int 27 } 28 29 const ( 30 growthFactor = float32(2.0) // growth by 100% 31 shrinkFactor = float32(0.25) // shrink when size is 25% of capacity (0 means never shrink) 32 ) 33 34 // New instantiates a new empty list 35 func New() *List { 36 return &List{} 37 } 38 39 // Add appends a value at the end of the list 40 func (list *List) Add(values ...interface{}) { 41 list.growBy(len(values)) 42 for _, value := range values { 43 list.elements[list.size] = value 44 list.size++ 45 } 46 } 47 48 // Get returns the element at index. 49 // Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false. 50 func (list *List) Get(index int) (interface{}, bool) { 51 52 if !list.withinRange(index) { 53 return nil, false 54 } 55 56 return list.elements[index], true 57 } 58 59 // Remove removes one or more elements from the list with the supplied indices. 60 func (list *List) Remove(index int) { 61 62 if !list.withinRange(index) { 63 return 64 } 65 66 list.elements[index] = nil // cleanup reference 67 copy(list.elements[index:], list.elements[index+1:list.size]) // shift to the left by one (slow operation, need ways to optimize this) 68 list.size-- 69 70 list.shrink() 71 } 72 73 // Contains checks if elements (one or more) are present in the set. 74 // All elements have to be present in the set for the method to return true. 75 // Performance time complexity of n^2. 76 // Returns true if no arguments are passed at all, i.e. set is always super-set of empty set. 77 func (list *List) Contains(values ...interface{}) bool { 78 79 for _, searchValue := range values { 80 found := false 81 for _, element := range list.elements { 82 if element == searchValue { 83 found = true 84 break 85 } 86 } 87 if !found { 88 return false 89 } 90 } 91 return true 92 } 93 94 // Values returns all elements in the list. 95 func (list *List) Values() []interface{} { 96 newElements := make([]interface{}, list.size, list.size) 97 copy(newElements, list.elements[:list.size]) 98 return newElements 99 } 100 101 //IndexOf returns index of provided element 102 func (list *List) IndexOf(value interface{}) int{ 103 if list.size == 0 { 104 return -1 105 } 106 for index, element := range list.elements { 107 if element == value { 108 return index 109 } 110 } 111 return -1 112 } 113 // Empty returns true if list does not contain any elements. 114 func (list *List) Empty() bool { 115 return list.size == 0 116 } 117 118 // Size returns number of elements within the list. 119 func (list *List) Size() int { 120 return list.size 121 } 122 123 // Clear removes all elements from the list. 124 func (list *List) Clear() { 125 list.size = 0 126 list.elements = []interface{}{} 127 } 128 129 // Sort sorts values (in-place) using. 130 func (list *List) Sort(comparator utils.Comparator) { 131 if len(list.elements) < 2 { 132 return 133 } 134 utils.Sort(list.elements[:list.size], comparator) 135 } 136 137 // Swap swaps the two values at the specified positions. 138 func (list *List) Swap(i, j int) { 139 if list.withinRange(i) && list.withinRange(j) { 140 list.elements[i], list.elements[j] = list.elements[j], list.elements[i] 141 } 142 } 143 144 // Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right. 145 // Does not do anything if position is negative or bigger than list's size 146 // Note: position equal to list's size is valid, i.e. append. 147 func (list *List) Insert(index int, values ...interface{}) { 148 149 if !list.withinRange(index) { 150 // Append 151 if index == list.size { 152 list.Add(values...) 153 } 154 return 155 } 156 157 l := len(values) 158 list.growBy(l) 159 list.size += l 160 // Shift old to right 161 for i := list.size - 1; i >= index+l; i-- { 162 list.elements[i] = list.elements[i-l] 163 } 164 // Insert new 165 for i, value := range values { 166 list.elements[index+i] = value 167 } 168 } 169 170 // String returns a string representation of container 171 func (list *List) String() string { 172 str := "ArrayList\n" 173 values := []string{} 174 for _, value := range list.elements[:list.size] { 175 values = append(values, fmt.Sprintf("%v", value)) 176 } 177 str += strings.Join(values, ", ") 178 return str 179 } 180 181 // Check that the index is within bounds of the list 182 func (list *List) withinRange(index int) bool { 183 return index >= 0 && index < list.size 184 } 185 186 func (list *List) resize(cap int) { 187 newElements := make([]interface{}, cap, cap) 188 copy(newElements, list.elements) 189 list.elements = newElements 190 } 191 192 // Expand the array if necessary, i.e. capacity will be reached if we add n elements 193 func (list *List) growBy(n int) { 194 // When capacity is reached, grow by a factor of growthFactor and add number of elements 195 currentCapacity := cap(list.elements) 196 if list.size+n >= currentCapacity { 197 newCapacity := int(growthFactor * float32(currentCapacity+n)) 198 list.resize(newCapacity) 199 } 200 } 201 202 // Shrink the array if necessary, i.e. when size is shrinkFactor percent of current capacity 203 func (list *List) shrink() { 204 if shrinkFactor == 0.0 { 205 return 206 } 207 // Shrink when size is at shrinkFactor * capacity 208 currentCapacity := cap(list.elements) 209 if list.size <= int(float32(currentCapacity)*shrinkFactor) { 210 list.resize(list.size) 211 } 212 }