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