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