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