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  }