github.com/zhongdalu/gf@v1.0.0/g/container/garray/garray_normal_int.go (about)

     1  // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/zhongdalu/gf.
     6  
     7  package garray
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/json"
    12  	"math"
    13  	"sort"
    14  
    15  	"github.com/zhongdalu/gf/g/internal/rwmutex"
    16  	"github.com/zhongdalu/gf/g/util/gconv"
    17  	"github.com/zhongdalu/gf/g/util/grand"
    18  )
    19  
    20  type IntArray struct {
    21  	mu    *rwmutex.RWMutex
    22  	array []int
    23  }
    24  
    25  // NewIntArray creates and returns an empty array.
    26  // The parameter <unsafe> used to specify whether using array in un-concurrent-safety,
    27  // which is false in default.
    28  func NewIntArray(unsafe ...bool) *IntArray {
    29  	return NewIntArraySize(0, 0, unsafe...)
    30  }
    31  
    32  // NewIntArraySize create and returns an array with given size and cap.
    33  // The parameter <unsafe> used to specify whether using array in un-concurrent-safety,
    34  // which is false in default.
    35  func NewIntArraySize(size int, cap int, unsafe ...bool) *IntArray {
    36  	return &IntArray{
    37  		mu:    rwmutex.New(unsafe...),
    38  		array: make([]int, size, cap),
    39  	}
    40  }
    41  
    42  // NewIntArrayFrom creates and returns an array with given slice <array>.
    43  // The parameter <unsafe> used to specify whether using array in un-concurrent-safety,
    44  // which is false in default.
    45  func NewIntArrayFrom(array []int, unsafe ...bool) *IntArray {
    46  	return &IntArray{
    47  		mu:    rwmutex.New(unsafe...),
    48  		array: array,
    49  	}
    50  }
    51  
    52  // NewIntArrayFromCopy creates and returns an array from a copy of given slice <array>.
    53  // The parameter <unsafe> used to specify whether using array in un-concurrent-safety,
    54  // which is false in default.
    55  func NewIntArrayFromCopy(array []int, unsafe ...bool) *IntArray {
    56  	newArray := make([]int, len(array))
    57  	copy(newArray, array)
    58  	return &IntArray{
    59  		mu:    rwmutex.New(unsafe...),
    60  		array: newArray,
    61  	}
    62  }
    63  
    64  // Get returns the value of the specified index,
    65  // the caller should notice the boundary of the array.
    66  func (a *IntArray) Get(index int) int {
    67  	a.mu.RLock()
    68  	defer a.mu.RUnlock()
    69  	value := a.array[index]
    70  	return value
    71  }
    72  
    73  // Set sets value to specified index.
    74  func (a *IntArray) Set(index int, value int) *IntArray {
    75  	a.mu.Lock()
    76  	defer a.mu.Unlock()
    77  	a.array[index] = value
    78  	return a
    79  }
    80  
    81  // SetArray sets the underlying slice array with the given <array>.
    82  func (a *IntArray) SetArray(array []int) *IntArray {
    83  	a.mu.Lock()
    84  	defer a.mu.Unlock()
    85  	a.array = array
    86  	return a
    87  }
    88  
    89  // Replace replaces the array items by given <array> from the beginning of array.
    90  func (a *IntArray) Replace(array []int) *IntArray {
    91  	a.mu.Lock()
    92  	defer a.mu.Unlock()
    93  	max := len(array)
    94  	if max > len(a.array) {
    95  		max = len(a.array)
    96  	}
    97  	for i := 0; i < max; i++ {
    98  		a.array[i] = array[i]
    99  	}
   100  	return a
   101  }
   102  
   103  // Sum returns the sum of values in an array.
   104  func (a *IntArray) Sum() (sum int) {
   105  	a.mu.RLock()
   106  	defer a.mu.RUnlock()
   107  	for _, v := range a.array {
   108  		sum += v
   109  	}
   110  	return
   111  }
   112  
   113  // Sort sorts the array in increasing order.
   114  // The parameter <reverse> controls whether sort
   115  // in increasing order(default) or decreasing order
   116  func (a *IntArray) Sort(reverse ...bool) *IntArray {
   117  	a.mu.Lock()
   118  	defer a.mu.Unlock()
   119  	if len(reverse) > 0 && reverse[0] {
   120  		sort.Slice(a.array, func(i, j int) bool {
   121  			if a.array[i] < a.array[j] {
   122  				return false
   123  			}
   124  			return true
   125  		})
   126  	} else {
   127  		sort.Ints(a.array)
   128  	}
   129  	return a
   130  }
   131  
   132  // SortFunc sorts the array by custom function <less>.
   133  func (a *IntArray) SortFunc(less func(v1, v2 int) bool) *IntArray {
   134  	a.mu.Lock()
   135  	defer a.mu.Unlock()
   136  	sort.Slice(a.array, func(i, j int) bool {
   137  		return less(a.array[i], a.array[j])
   138  	})
   139  	return a
   140  }
   141  
   142  // InsertBefore inserts the <value> to the front of <index>.
   143  func (a *IntArray) InsertBefore(index int, value int) *IntArray {
   144  	a.mu.Lock()
   145  	defer a.mu.Unlock()
   146  	rear := append([]int{}, a.array[index:]...)
   147  	a.array = append(a.array[0:index], value)
   148  	a.array = append(a.array, rear...)
   149  	return a
   150  }
   151  
   152  // InsertAfter inserts the <value> to the back of <index>.
   153  func (a *IntArray) InsertAfter(index int, value int) *IntArray {
   154  	a.mu.Lock()
   155  	defer a.mu.Unlock()
   156  	rear := append([]int{}, a.array[index+1:]...)
   157  	a.array = append(a.array[0:index+1], value)
   158  	a.array = append(a.array, rear...)
   159  	return a
   160  }
   161  
   162  // Remove removes an item by index.
   163  func (a *IntArray) Remove(index int) int {
   164  	a.mu.Lock()
   165  	defer a.mu.Unlock()
   166  	// Determine array boundaries when deleting to improve deletion efficiency.
   167  	if index == 0 {
   168  		value := a.array[0]
   169  		a.array = a.array[1:]
   170  		return value
   171  	} else if index == len(a.array)-1 {
   172  		value := a.array[index]
   173  		a.array = a.array[:index]
   174  		return value
   175  	}
   176  	// If it is a non-boundary delete,
   177  	// it will involve the creation of an array,
   178  	// then the deletion is less efficient.
   179  	value := a.array[index]
   180  	a.array = append(a.array[:index], a.array[index+1:]...)
   181  	return value
   182  }
   183  
   184  // PushLeft pushes one or multiple items to the beginning of array.
   185  func (a *IntArray) PushLeft(value ...int) *IntArray {
   186  	a.mu.Lock()
   187  	a.array = append(value, a.array...)
   188  	a.mu.Unlock()
   189  	return a
   190  }
   191  
   192  // PushRight pushes one or multiple items to the end of array.
   193  // It equals to Append.
   194  func (a *IntArray) PushRight(value ...int) *IntArray {
   195  	a.mu.Lock()
   196  	a.array = append(a.array, value...)
   197  	a.mu.Unlock()
   198  	return a
   199  }
   200  
   201  // PopLeft pops and returns an item from the beginning of array.
   202  func (a *IntArray) PopLeft() int {
   203  	a.mu.Lock()
   204  	defer a.mu.Unlock()
   205  	value := a.array[0]
   206  	a.array = a.array[1:]
   207  	return value
   208  }
   209  
   210  // PopRight pops and returns an item from the end of array.
   211  func (a *IntArray) PopRight() int {
   212  	a.mu.Lock()
   213  	defer a.mu.Unlock()
   214  	index := len(a.array) - 1
   215  	value := a.array[index]
   216  	a.array = a.array[:index]
   217  	return value
   218  }
   219  
   220  // PopRand randomly pops and return an item out of array.
   221  func (a *IntArray) PopRand() int {
   222  	return a.Remove(grand.Intn(len(a.array)))
   223  }
   224  
   225  // PopRands randomly pops and returns <size> items out of array.
   226  func (a *IntArray) PopRands(size int) []int {
   227  	a.mu.Lock()
   228  	defer a.mu.Unlock()
   229  	if size > len(a.array) {
   230  		size = len(a.array)
   231  	}
   232  	array := make([]int, size)
   233  	for i := 0; i < size; i++ {
   234  		index := grand.Intn(len(a.array))
   235  		array[i] = a.array[index]
   236  		a.array = append(a.array[:index], a.array[index+1:]...)
   237  	}
   238  	return array
   239  }
   240  
   241  // PopLefts pops and returns <size> items from the beginning of array.
   242  func (a *IntArray) PopLefts(size int) []int {
   243  	a.mu.Lock()
   244  	defer a.mu.Unlock()
   245  	length := len(a.array)
   246  	if size > length {
   247  		size = length
   248  	}
   249  	value := a.array[0:size]
   250  	a.array = a.array[size:]
   251  	return value
   252  }
   253  
   254  // PopRights pops and returns <size> items from the end of array.
   255  func (a *IntArray) PopRights(size int) []int {
   256  	a.mu.Lock()
   257  	defer a.mu.Unlock()
   258  	index := len(a.array) - size
   259  	if index < 0 {
   260  		index = 0
   261  	}
   262  	value := a.array[index:]
   263  	a.array = a.array[:index]
   264  	return value
   265  }
   266  
   267  // Range picks and returns items by range, like array[start:end].
   268  // Notice, if in concurrent-safe usage, it returns a copy of slice;
   269  // else a pointer to the underlying data.
   270  //
   271  // If <end> is negative, then the offset will start from the end of array.
   272  // If <end> is omitted, then the sequence will have everything from start up
   273  // until the end of the array.
   274  func (a *IntArray) Range(start int, end ...int) []int {
   275  	a.mu.RLock()
   276  	defer a.mu.RUnlock()
   277  	offsetEnd := len(a.array)
   278  	if len(end) > 0 && end[0] < offsetEnd {
   279  		offsetEnd = end[0]
   280  	}
   281  	if start > offsetEnd {
   282  		return nil
   283  	}
   284  	if start < 0 {
   285  		start = 0
   286  	}
   287  	array := ([]int)(nil)
   288  	if a.mu.IsSafe() {
   289  		array = make([]int, offsetEnd-start)
   290  		copy(array, a.array[start:offsetEnd])
   291  	} else {
   292  		array = a.array[start:offsetEnd]
   293  	}
   294  	return array
   295  }
   296  
   297  // SubSlice returns a slice of elements from the array as specified
   298  // by the <offset> and <size> parameters.
   299  // If in concurrent safe usage, it returns a copy of the slice; else a pointer.
   300  //
   301  // If offset is non-negative, the sequence will start at that offset in the array.
   302  // If offset is negative, the sequence will start that far from the end of the array.
   303  //
   304  // If length is given and is positive, then the sequence will have up to that many elements in it.
   305  // If the array is shorter than the length, then only the available array elements will be present.
   306  // If length is given and is negative then the sequence will stop that many elements from the end of the array.
   307  // If it is omitted, then the sequence will have everything from offset up until the end of the array.
   308  //
   309  // Any possibility crossing the left border of array, it will fail.
   310  func (a *IntArray) SubSlice(offset int, length ...int) []int {
   311  	a.mu.RLock()
   312  	defer a.mu.RUnlock()
   313  	size := len(a.array)
   314  	if len(length) > 0 {
   315  		size = length[0]
   316  	}
   317  	if offset > len(a.array) {
   318  		return nil
   319  	}
   320  	if offset < 0 {
   321  		offset = len(a.array) + offset
   322  		if offset < 0 {
   323  			return nil
   324  		}
   325  	}
   326  	if size < 0 {
   327  		offset += size
   328  		size = -size
   329  		if offset < 0 {
   330  			return nil
   331  		}
   332  	}
   333  	end := offset + size
   334  	if end > len(a.array) {
   335  		end = len(a.array)
   336  		size = len(a.array) - offset
   337  	}
   338  	if a.mu.IsSafe() {
   339  		s := make([]int, size)
   340  		copy(s, a.array[offset:])
   341  		return s
   342  	} else {
   343  		return a.array[offset:end]
   344  	}
   345  }
   346  
   347  // See PushRight.
   348  func (a *IntArray) Append(value ...int) *IntArray {
   349  	a.mu.Lock()
   350  	a.array = append(a.array, value...)
   351  	a.mu.Unlock()
   352  	return a
   353  }
   354  
   355  // Len returns the length of array.
   356  func (a *IntArray) Len() int {
   357  	a.mu.RLock()
   358  	length := len(a.array)
   359  	a.mu.RUnlock()
   360  	return length
   361  }
   362  
   363  // Slice returns the underlying data of array.
   364  // Notice, if in concurrent-safe usage, it returns a copy of slice;
   365  // else a pointer to the underlying data.
   366  func (a *IntArray) Slice() []int {
   367  	array := ([]int)(nil)
   368  	if a.mu.IsSafe() {
   369  		a.mu.RLock()
   370  		defer a.mu.RUnlock()
   371  		array = make([]int, len(a.array))
   372  		copy(array, a.array)
   373  	} else {
   374  		array = a.array
   375  	}
   376  	return array
   377  }
   378  
   379  // Clone returns a new array, which is a copy of current array.
   380  func (a *IntArray) Clone() (newArray *IntArray) {
   381  	a.mu.RLock()
   382  	array := make([]int, len(a.array))
   383  	copy(array, a.array)
   384  	a.mu.RUnlock()
   385  	return NewIntArrayFrom(array, !a.mu.IsSafe())
   386  }
   387  
   388  // Clear deletes all items of current array.
   389  func (a *IntArray) Clear() *IntArray {
   390  	a.mu.Lock()
   391  	if len(a.array) > 0 {
   392  		a.array = make([]int, 0)
   393  	}
   394  	a.mu.Unlock()
   395  	return a
   396  }
   397  
   398  // Contains checks whether a value exists in the array.
   399  func (a *IntArray) Contains(value int) bool {
   400  	return a.Search(value) != -1
   401  }
   402  
   403  // Search searches array by <value>, returns the index of <value>,
   404  // or returns -1 if not exists.
   405  func (a *IntArray) Search(value int) int {
   406  	if len(a.array) == 0 {
   407  		return -1
   408  	}
   409  	a.mu.RLock()
   410  	result := -1
   411  	for index, v := range a.array {
   412  		if v == value {
   413  			result = index
   414  			break
   415  		}
   416  	}
   417  	a.mu.RUnlock()
   418  
   419  	return result
   420  }
   421  
   422  // Unique uniques the array, clear repeated items.
   423  func (a *IntArray) Unique() *IntArray {
   424  	a.mu.Lock()
   425  	for i := 0; i < len(a.array)-1; i++ {
   426  		for j := i + 1; j < len(a.array); j++ {
   427  			if a.array[i] == a.array[j] {
   428  				a.array = append(a.array[:j], a.array[j+1:]...)
   429  			}
   430  		}
   431  	}
   432  	a.mu.Unlock()
   433  	return a
   434  }
   435  
   436  // LockFunc locks writing by callback function <f>.
   437  func (a *IntArray) LockFunc(f func(array []int)) *IntArray {
   438  	a.mu.Lock()
   439  	defer a.mu.Unlock()
   440  	f(a.array)
   441  	return a
   442  }
   443  
   444  // RLockFunc locks reading by callback function <f>.
   445  func (a *IntArray) RLockFunc(f func(array []int)) *IntArray {
   446  	a.mu.RLock()
   447  	defer a.mu.RUnlock()
   448  	f(a.array)
   449  	return a
   450  }
   451  
   452  // Merge merges <array> into current array.
   453  // The parameter <array> can be any garray or slice type.
   454  // The difference between Merge and Append is Append supports only specified slice type,
   455  // but Merge supports more parameter types.
   456  func (a *IntArray) Merge(array interface{}) *IntArray {
   457  	switch v := array.(type) {
   458  	case *Array:
   459  		a.Append(gconv.Ints(v.Slice())...)
   460  	case *IntArray:
   461  		a.Append(gconv.Ints(v.Slice())...)
   462  	case *StringArray:
   463  		a.Append(gconv.Ints(v.Slice())...)
   464  	case *SortedArray:
   465  		a.Append(gconv.Ints(v.Slice())...)
   466  	case *SortedIntArray:
   467  		a.Append(gconv.Ints(v.Slice())...)
   468  	case *SortedStringArray:
   469  		a.Append(gconv.Ints(v.Slice())...)
   470  	default:
   471  		a.Append(gconv.Ints(array)...)
   472  	}
   473  	return a
   474  }
   475  
   476  // Fill fills an array with num entries of the value <value>,
   477  // keys starting at the <startIndex> parameter.
   478  func (a *IntArray) Fill(startIndex int, num int, value int) *IntArray {
   479  	a.mu.Lock()
   480  	defer a.mu.Unlock()
   481  	if startIndex < 0 {
   482  		startIndex = 0
   483  	}
   484  	for i := startIndex; i < startIndex+num; i++ {
   485  		if i > len(a.array)-1 {
   486  			a.array = append(a.array, value)
   487  		} else {
   488  			a.array[i] = value
   489  		}
   490  	}
   491  	return a
   492  }
   493  
   494  // Chunk splits an array into multiple arrays,
   495  // the size of each array is determined by <size>.
   496  // The last chunk may contain less than size elements.
   497  func (a *IntArray) Chunk(size int) [][]int {
   498  	if size < 1 {
   499  		return nil
   500  	}
   501  	a.mu.RLock()
   502  	defer a.mu.RUnlock()
   503  	length := len(a.array)
   504  	chunks := int(math.Ceil(float64(length) / float64(size)))
   505  	var n [][]int
   506  	for i, end := 0, 0; chunks > 0; chunks-- {
   507  		end = (i + 1) * size
   508  		if end > length {
   509  			end = length
   510  		}
   511  		n = append(n, a.array[i*size:end])
   512  		i++
   513  	}
   514  	return n
   515  }
   516  
   517  // Pad pads array to the specified length with <value>.
   518  // If size is positive then the array is padded on the right, or negative on the left.
   519  // If the absolute value of <size> is less than or equal to the length of the array
   520  // then no padding takes place.
   521  func (a *IntArray) Pad(size int, value int) *IntArray {
   522  	a.mu.Lock()
   523  	defer a.mu.Unlock()
   524  	if size == 0 || (size > 0 && size < len(a.array)) || (size < 0 && size > -len(a.array)) {
   525  		return a
   526  	}
   527  	n := size
   528  	if size < 0 {
   529  		n = -size
   530  	}
   531  	n -= len(a.array)
   532  	tmp := make([]int, n)
   533  	for i := 0; i < n; i++ {
   534  		tmp[i] = value
   535  	}
   536  	if size > 0 {
   537  		a.array = append(a.array, tmp...)
   538  	} else {
   539  		a.array = append(tmp, a.array...)
   540  	}
   541  	return a
   542  }
   543  
   544  // Rand randomly returns one item from array(no deleting).
   545  func (a *IntArray) Rand() int {
   546  	a.mu.RLock()
   547  	defer a.mu.RUnlock()
   548  	return a.array[grand.Intn(len(a.array))]
   549  }
   550  
   551  // Rands randomly returns <size> items from array(no deleting).
   552  func (a *IntArray) Rands(size int) []int {
   553  	a.mu.RLock()
   554  	defer a.mu.RUnlock()
   555  	if size > len(a.array) {
   556  		size = len(a.array)
   557  	}
   558  	n := make([]int, size)
   559  	for i, v := range grand.Perm(len(a.array)) {
   560  		n[i] = a.array[v]
   561  		if i == size-1 {
   562  			break
   563  		}
   564  	}
   565  	return n
   566  }
   567  
   568  // Shuffle randomly shuffles the array.
   569  func (a *IntArray) Shuffle() *IntArray {
   570  	a.mu.Lock()
   571  	defer a.mu.Unlock()
   572  	for i, v := range grand.Perm(len(a.array)) {
   573  		a.array[i], a.array[v] = a.array[v], a.array[i]
   574  	}
   575  	return a
   576  }
   577  
   578  // Reverse makes array with elements in reverse order.
   579  func (a *IntArray) Reverse() *IntArray {
   580  	a.mu.Lock()
   581  	defer a.mu.Unlock()
   582  	for i, j := 0, len(a.array)-1; i < j; i, j = i+1, j-1 {
   583  		a.array[i], a.array[j] = a.array[j], a.array[i]
   584  	}
   585  	return a
   586  }
   587  
   588  // Join joins array elements with a string <glue>.
   589  func (a *IntArray) Join(glue string) string {
   590  	a.mu.RLock()
   591  	defer a.mu.RUnlock()
   592  	buffer := bytes.NewBuffer(nil)
   593  	for k, v := range a.array {
   594  		buffer.WriteString(gconv.String(v))
   595  		if k != len(a.array)-1 {
   596  			buffer.WriteString(glue)
   597  		}
   598  	}
   599  	return buffer.String()
   600  }
   601  
   602  // CountValues counts the number of occurrences of all values in the array.
   603  func (a *IntArray) CountValues() map[int]int {
   604  	m := make(map[int]int)
   605  	a.mu.RLock()
   606  	defer a.mu.RUnlock()
   607  	for _, v := range a.array {
   608  		m[v]++
   609  	}
   610  	return m
   611  }
   612  
   613  // String returns current array as a string.
   614  func (a *IntArray) String() string {
   615  	a.mu.RLock()
   616  	defer a.mu.RUnlock()
   617  	jsonContent, _ := json.Marshal(a.array)
   618  	return string(jsonContent)
   619  }
   620  
   621  // MarshalJSON implements the interface MarshalJSON for json.Marshal.
   622  func (a *IntArray) MarshalJSON() ([]byte, error) {
   623  	a.mu.RLock()
   624  	defer a.mu.RUnlock()
   625  	return json.Marshal(a.array)
   626  }