github.com/gogf/gf/v2@v2.7.4/container/garray/garray_sorted_str.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). 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/gogf/gf.
     6  
     7  package garray
     8  
     9  import (
    10  	"bytes"
    11  	"math"
    12  	"sort"
    13  	"strings"
    14  
    15  	"github.com/gogf/gf/v2/internal/json"
    16  	"github.com/gogf/gf/v2/internal/rwmutex"
    17  	"github.com/gogf/gf/v2/text/gstr"
    18  	"github.com/gogf/gf/v2/util/gconv"
    19  	"github.com/gogf/gf/v2/util/grand"
    20  )
    21  
    22  // SortedStrArray is a golang sorted string array with rich features.
    23  // It is using increasing order in default, which can be changed by
    24  // setting it a custom comparator.
    25  // It contains a concurrent-safe/unsafe switch, which should be set
    26  // when its initialization and cannot be changed then.
    27  type SortedStrArray struct {
    28  	mu         rwmutex.RWMutex
    29  	array      []string
    30  	unique     bool                  // Whether enable unique feature(false)
    31  	comparator func(a, b string) int // Comparison function(it returns -1: a < b; 0: a == b; 1: a > b)
    32  }
    33  
    34  // NewSortedStrArray creates and returns an empty sorted array.
    35  // The parameter `safe` is used to specify whether using array in concurrent-safety,
    36  // which is false in default.
    37  func NewSortedStrArray(safe ...bool) *SortedStrArray {
    38  	return NewSortedStrArraySize(0, safe...)
    39  }
    40  
    41  // NewSortedStrArrayComparator creates and returns an empty sorted array with specified comparator.
    42  // The parameter `safe` is used to specify whether using array in concurrent-safety which is false in default.
    43  func NewSortedStrArrayComparator(comparator func(a, b string) int, safe ...bool) *SortedStrArray {
    44  	array := NewSortedStrArray(safe...)
    45  	array.comparator = comparator
    46  	return array
    47  }
    48  
    49  // NewSortedStrArraySize create and returns an sorted array with given size and cap.
    50  // The parameter `safe` is used to specify whether using array in concurrent-safety,
    51  // which is false in default.
    52  func NewSortedStrArraySize(cap int, safe ...bool) *SortedStrArray {
    53  	return &SortedStrArray{
    54  		mu:         rwmutex.Create(safe...),
    55  		array:      make([]string, 0, cap),
    56  		comparator: defaultComparatorStr,
    57  	}
    58  }
    59  
    60  // NewSortedStrArrayFrom creates and returns an sorted array with given slice `array`.
    61  // The parameter `safe` is used to specify whether using array in concurrent-safety,
    62  // which is false in default.
    63  func NewSortedStrArrayFrom(array []string, safe ...bool) *SortedStrArray {
    64  	a := NewSortedStrArraySize(0, safe...)
    65  	a.array = array
    66  	quickSortStr(a.array, a.getComparator())
    67  	return a
    68  }
    69  
    70  // NewSortedStrArrayFromCopy creates and returns an sorted array from a copy of given slice `array`.
    71  // The parameter `safe` is used to specify whether using array in concurrent-safety,
    72  // which is false in default.
    73  func NewSortedStrArrayFromCopy(array []string, safe ...bool) *SortedStrArray {
    74  	newArray := make([]string, len(array))
    75  	copy(newArray, array)
    76  	return NewSortedStrArrayFrom(newArray, safe...)
    77  }
    78  
    79  // SetArray sets the underlying slice array with the given `array`.
    80  func (a *SortedStrArray) SetArray(array []string) *SortedStrArray {
    81  	a.mu.Lock()
    82  	defer a.mu.Unlock()
    83  	a.array = array
    84  	quickSortStr(a.array, a.getComparator())
    85  	return a
    86  }
    87  
    88  // At returns the value by the specified index.
    89  // If the given `index` is out of range of the array, it returns an empty string.
    90  func (a *SortedStrArray) At(index int) (value string) {
    91  	value, _ = a.Get(index)
    92  	return
    93  }
    94  
    95  // Sort sorts the array in increasing order.
    96  // The parameter `reverse` controls whether sort
    97  // in increasing order(default) or decreasing order.
    98  func (a *SortedStrArray) Sort() *SortedStrArray {
    99  	a.mu.Lock()
   100  	defer a.mu.Unlock()
   101  	quickSortStr(a.array, a.getComparator())
   102  	return a
   103  }
   104  
   105  // Add adds one or multiple values to sorted array, the array always keeps sorted.
   106  // It's alias of function Append, see Append.
   107  func (a *SortedStrArray) Add(values ...string) *SortedStrArray {
   108  	return a.Append(values...)
   109  }
   110  
   111  // Append adds one or multiple values to sorted array, the array always keeps sorted.
   112  func (a *SortedStrArray) Append(values ...string) *SortedStrArray {
   113  	if len(values) == 0 {
   114  		return a
   115  	}
   116  	a.mu.Lock()
   117  	defer a.mu.Unlock()
   118  	for _, value := range values {
   119  		index, cmp := a.binSearch(value, false)
   120  		if a.unique && cmp == 0 {
   121  			continue
   122  		}
   123  		if index < 0 {
   124  			a.array = append(a.array, value)
   125  			continue
   126  		}
   127  		if cmp > 0 {
   128  			index++
   129  		}
   130  		rear := append([]string{}, a.array[index:]...)
   131  		a.array = append(a.array[0:index], value)
   132  		a.array = append(a.array, rear...)
   133  	}
   134  	return a
   135  }
   136  
   137  // Get returns the value by the specified index.
   138  // If the given `index` is out of range of the array, the `found` is false.
   139  func (a *SortedStrArray) Get(index int) (value string, found bool) {
   140  	a.mu.RLock()
   141  	defer a.mu.RUnlock()
   142  	if index < 0 || index >= len(a.array) {
   143  		return "", false
   144  	}
   145  	return a.array[index], true
   146  }
   147  
   148  // Remove removes an item by index.
   149  // If the given `index` is out of range of the array, the `found` is false.
   150  func (a *SortedStrArray) Remove(index int) (value string, found bool) {
   151  	a.mu.Lock()
   152  	defer a.mu.Unlock()
   153  	return a.doRemoveWithoutLock(index)
   154  }
   155  
   156  // doRemoveWithoutLock removes an item by index without lock.
   157  func (a *SortedStrArray) doRemoveWithoutLock(index int) (value string, found bool) {
   158  	if index < 0 || index >= len(a.array) {
   159  		return "", false
   160  	}
   161  	// Determine array boundaries when deleting to improve deletion efficiency.
   162  	if index == 0 {
   163  		value := a.array[0]
   164  		a.array = a.array[1:]
   165  		return value, true
   166  	} else if index == len(a.array)-1 {
   167  		value := a.array[index]
   168  		a.array = a.array[:index]
   169  		return value, true
   170  	}
   171  	// If it is a non-boundary delete,
   172  	// it will involve the creation of an array,
   173  	// then the deletion is less efficient.
   174  	value = a.array[index]
   175  	a.array = append(a.array[:index], a.array[index+1:]...)
   176  	return value, true
   177  }
   178  
   179  // RemoveValue removes an item by value.
   180  // It returns true if value is found in the array, or else false if not found.
   181  func (a *SortedStrArray) RemoveValue(value string) bool {
   182  	a.mu.Lock()
   183  	defer a.mu.Unlock()
   184  	if i, r := a.binSearch(value, false); r == 0 {
   185  		_, res := a.doRemoveWithoutLock(i)
   186  		return res
   187  	}
   188  	return false
   189  }
   190  
   191  // RemoveValues removes an item by `values`.
   192  func (a *SortedStrArray) RemoveValues(values ...string) {
   193  	a.mu.Lock()
   194  	defer a.mu.Unlock()
   195  	for _, value := range values {
   196  		if i, r := a.binSearch(value, false); r == 0 {
   197  			a.doRemoveWithoutLock(i)
   198  		}
   199  	}
   200  }
   201  
   202  // PopLeft pops and returns an item from the beginning of array.
   203  // Note that if the array is empty, the `found` is false.
   204  func (a *SortedStrArray) PopLeft() (value string, found bool) {
   205  	a.mu.Lock()
   206  	defer a.mu.Unlock()
   207  	if len(a.array) == 0 {
   208  		return "", false
   209  	}
   210  	value = a.array[0]
   211  	a.array = a.array[1:]
   212  	return value, true
   213  }
   214  
   215  // PopRight pops and returns an item from the end of array.
   216  // Note that if the array is empty, the `found` is false.
   217  func (a *SortedStrArray) PopRight() (value string, found bool) {
   218  	a.mu.Lock()
   219  	defer a.mu.Unlock()
   220  	index := len(a.array) - 1
   221  	if index < 0 {
   222  		return "", false
   223  	}
   224  	value = a.array[index]
   225  	a.array = a.array[:index]
   226  	return value, true
   227  }
   228  
   229  // PopRand randomly pops and return an item out of array.
   230  // Note that if the array is empty, the `found` is false.
   231  func (a *SortedStrArray) PopRand() (value string, found bool) {
   232  	a.mu.Lock()
   233  	defer a.mu.Unlock()
   234  	return a.doRemoveWithoutLock(grand.Intn(len(a.array)))
   235  }
   236  
   237  // PopRands randomly pops and returns `size` items out of array.
   238  // If the given `size` is greater than size of the array, it returns all elements of the array.
   239  // Note that if given `size` <= 0 or the array is empty, it returns nil.
   240  func (a *SortedStrArray) PopRands(size int) []string {
   241  	a.mu.Lock()
   242  	defer a.mu.Unlock()
   243  	if size <= 0 || len(a.array) == 0 {
   244  		return nil
   245  	}
   246  	if size >= len(a.array) {
   247  		size = len(a.array)
   248  	}
   249  	array := make([]string, size)
   250  	for i := 0; i < size; i++ {
   251  		array[i], _ = a.doRemoveWithoutLock(grand.Intn(len(a.array)))
   252  	}
   253  	return array
   254  }
   255  
   256  // PopLefts pops and returns `size` items from the beginning of array.
   257  // If the given `size` is greater than size of the array, it returns all elements of the array.
   258  // Note that if given `size` <= 0 or the array is empty, it returns nil.
   259  func (a *SortedStrArray) PopLefts(size int) []string {
   260  	a.mu.Lock()
   261  	defer a.mu.Unlock()
   262  	if size <= 0 || len(a.array) == 0 {
   263  		return nil
   264  	}
   265  	if size >= len(a.array) {
   266  		array := a.array
   267  		a.array = a.array[:0]
   268  		return array
   269  	}
   270  	value := a.array[0:size]
   271  	a.array = a.array[size:]
   272  	return value
   273  }
   274  
   275  // PopRights pops and returns `size` items from the end of array.
   276  // If the given `size` is greater than size of the array, it returns all elements of the array.
   277  // Note that if given `size` <= 0 or the array is empty, it returns nil.
   278  func (a *SortedStrArray) PopRights(size int) []string {
   279  	a.mu.Lock()
   280  	defer a.mu.Unlock()
   281  	if size <= 0 || len(a.array) == 0 {
   282  		return nil
   283  	}
   284  	index := len(a.array) - size
   285  	if index <= 0 {
   286  		array := a.array
   287  		a.array = a.array[:0]
   288  		return array
   289  	}
   290  	value := a.array[index:]
   291  	a.array = a.array[:index]
   292  	return value
   293  }
   294  
   295  // Range picks and returns items by range, like array[start:end].
   296  // Notice, if in concurrent-safe usage, it returns a copy of slice;
   297  // else a pointer to the underlying data.
   298  //
   299  // If `end` is negative, then the offset will start from the end of array.
   300  // If `end` is omitted, then the sequence will have everything from start up
   301  // until the end of the array.
   302  func (a *SortedStrArray) Range(start int, end ...int) []string {
   303  	a.mu.RLock()
   304  	defer a.mu.RUnlock()
   305  	offsetEnd := len(a.array)
   306  	if len(end) > 0 && end[0] < offsetEnd {
   307  		offsetEnd = end[0]
   308  	}
   309  	if start > offsetEnd {
   310  		return nil
   311  	}
   312  	if start < 0 {
   313  		start = 0
   314  	}
   315  	array := ([]string)(nil)
   316  	if a.mu.IsSafe() {
   317  		array = make([]string, offsetEnd-start)
   318  		copy(array, a.array[start:offsetEnd])
   319  	} else {
   320  		array = a.array[start:offsetEnd]
   321  	}
   322  	return array
   323  }
   324  
   325  // SubSlice returns a slice of elements from the array as specified
   326  // by the `offset` and `size` parameters.
   327  // If in concurrent safe usage, it returns a copy of the slice; else a pointer.
   328  //
   329  // If offset is non-negative, the sequence will start at that offset in the array.
   330  // If offset is negative, the sequence will start that far from the end of the array.
   331  //
   332  // If length is given and is positive, then the sequence will have up to that many elements in it.
   333  // If the array is shorter than the length, then only the available array elements will be present.
   334  // If length is given and is negative then the sequence will stop that many elements from the end of the array.
   335  // If it is omitted, then the sequence will have everything from offset up until the end of the array.
   336  //
   337  // Any possibility crossing the left border of array, it will fail.
   338  func (a *SortedStrArray) SubSlice(offset int, length ...int) []string {
   339  	a.mu.RLock()
   340  	defer a.mu.RUnlock()
   341  	size := len(a.array)
   342  	if len(length) > 0 {
   343  		size = length[0]
   344  	}
   345  	if offset > len(a.array) {
   346  		return nil
   347  	}
   348  	if offset < 0 {
   349  		offset = len(a.array) + offset
   350  		if offset < 0 {
   351  			return nil
   352  		}
   353  	}
   354  	if size < 0 {
   355  		offset += size
   356  		size = -size
   357  		if offset < 0 {
   358  			return nil
   359  		}
   360  	}
   361  	end := offset + size
   362  	if end > len(a.array) {
   363  		end = len(a.array)
   364  		size = len(a.array) - offset
   365  	}
   366  	if a.mu.IsSafe() {
   367  		s := make([]string, size)
   368  		copy(s, a.array[offset:])
   369  		return s
   370  	} else {
   371  		return a.array[offset:end]
   372  	}
   373  }
   374  
   375  // Sum returns the sum of values in an array.
   376  func (a *SortedStrArray) Sum() (sum int) {
   377  	a.mu.RLock()
   378  	defer a.mu.RUnlock()
   379  	for _, v := range a.array {
   380  		sum += gconv.Int(v)
   381  	}
   382  	return
   383  }
   384  
   385  // Len returns the length of array.
   386  func (a *SortedStrArray) Len() int {
   387  	a.mu.RLock()
   388  	length := len(a.array)
   389  	a.mu.RUnlock()
   390  	return length
   391  }
   392  
   393  // Slice returns the underlying data of array.
   394  // Note that, if it's in concurrent-safe usage, it returns a copy of underlying data,
   395  // or else a pointer to the underlying data.
   396  func (a *SortedStrArray) Slice() []string {
   397  	array := ([]string)(nil)
   398  	if a.mu.IsSafe() {
   399  		a.mu.RLock()
   400  		defer a.mu.RUnlock()
   401  		array = make([]string, len(a.array))
   402  		copy(array, a.array)
   403  	} else {
   404  		array = a.array
   405  	}
   406  	return array
   407  }
   408  
   409  // Interfaces returns current array as []interface{}.
   410  func (a *SortedStrArray) Interfaces() []interface{} {
   411  	a.mu.RLock()
   412  	defer a.mu.RUnlock()
   413  	array := make([]interface{}, len(a.array))
   414  	for k, v := range a.array {
   415  		array[k] = v
   416  	}
   417  	return array
   418  }
   419  
   420  // Contains checks whether a value exists in the array.
   421  func (a *SortedStrArray) Contains(value string) bool {
   422  	return a.Search(value) != -1
   423  }
   424  
   425  // ContainsI checks whether a value exists in the array with case-insensitively.
   426  // Note that it internally iterates the whole array to do the comparison with case-insensitively.
   427  func (a *SortedStrArray) ContainsI(value string) bool {
   428  	a.mu.RLock()
   429  	defer a.mu.RUnlock()
   430  	if len(a.array) == 0 {
   431  		return false
   432  	}
   433  	for _, v := range a.array {
   434  		if strings.EqualFold(v, value) {
   435  			return true
   436  		}
   437  	}
   438  	return false
   439  }
   440  
   441  // Search searches array by `value`, returns the index of `value`,
   442  // or returns -1 if not exists.
   443  func (a *SortedStrArray) Search(value string) (index int) {
   444  	if i, r := a.binSearch(value, true); r == 0 {
   445  		return i
   446  	}
   447  	return -1
   448  }
   449  
   450  // Binary search.
   451  // It returns the last compared index and the result.
   452  // If `result` equals to 0, it means the value at `index` is equals to `value`.
   453  // If `result` lesser than 0, it means the value at `index` is lesser than `value`.
   454  // If `result` greater than 0, it means the value at `index` is greater than `value`.
   455  func (a *SortedStrArray) binSearch(value string, lock bool) (index int, result int) {
   456  	if lock {
   457  		a.mu.RLock()
   458  		defer a.mu.RUnlock()
   459  	}
   460  	if len(a.array) == 0 {
   461  		return -1, -2
   462  	}
   463  	min := 0
   464  	max := len(a.array) - 1
   465  	mid := 0
   466  	cmp := -2
   467  	for min <= max {
   468  		mid = min + int((max-min)/2)
   469  		cmp = a.getComparator()(value, a.array[mid])
   470  		switch {
   471  		case cmp < 0:
   472  			max = mid - 1
   473  		case cmp > 0:
   474  			min = mid + 1
   475  		default:
   476  			return mid, cmp
   477  		}
   478  	}
   479  	return mid, cmp
   480  }
   481  
   482  // SetUnique sets unique mark to the array,
   483  // which means it does not contain any repeated items.
   484  // It also do unique check, remove all repeated items.
   485  func (a *SortedStrArray) SetUnique(unique bool) *SortedStrArray {
   486  	oldUnique := a.unique
   487  	a.unique = unique
   488  	if unique && oldUnique != unique {
   489  		a.Unique()
   490  	}
   491  	return a
   492  }
   493  
   494  // Unique uniques the array, clear repeated items.
   495  func (a *SortedStrArray) Unique() *SortedStrArray {
   496  	a.mu.Lock()
   497  	defer a.mu.Unlock()
   498  	if len(a.array) == 0 {
   499  		return a
   500  	}
   501  	i := 0
   502  	for {
   503  		if i == len(a.array)-1 {
   504  			break
   505  		}
   506  		if a.getComparator()(a.array[i], a.array[i+1]) == 0 {
   507  			a.array = append(a.array[:i+1], a.array[i+1+1:]...)
   508  		} else {
   509  			i++
   510  		}
   511  	}
   512  	return a
   513  }
   514  
   515  // Clone returns a new array, which is a copy of current array.
   516  func (a *SortedStrArray) Clone() (newArray *SortedStrArray) {
   517  	a.mu.RLock()
   518  	array := make([]string, len(a.array))
   519  	copy(array, a.array)
   520  	a.mu.RUnlock()
   521  	return NewSortedStrArrayFrom(array, a.mu.IsSafe())
   522  }
   523  
   524  // Clear deletes all items of current array.
   525  func (a *SortedStrArray) Clear() *SortedStrArray {
   526  	a.mu.Lock()
   527  	if len(a.array) > 0 {
   528  		a.array = make([]string, 0)
   529  	}
   530  	a.mu.Unlock()
   531  	return a
   532  }
   533  
   534  // LockFunc locks writing by callback function `f`.
   535  func (a *SortedStrArray) LockFunc(f func(array []string)) *SortedStrArray {
   536  	a.mu.Lock()
   537  	defer a.mu.Unlock()
   538  	f(a.array)
   539  	return a
   540  }
   541  
   542  // RLockFunc locks reading by callback function `f`.
   543  func (a *SortedStrArray) RLockFunc(f func(array []string)) *SortedStrArray {
   544  	a.mu.RLock()
   545  	defer a.mu.RUnlock()
   546  	f(a.array)
   547  	return a
   548  }
   549  
   550  // Merge merges `array` into current array.
   551  // The parameter `array` can be any garray or slice type.
   552  // The difference between Merge and Append is Append supports only specified slice type,
   553  // but Merge supports more parameter types.
   554  func (a *SortedStrArray) Merge(array interface{}) *SortedStrArray {
   555  	return a.Add(gconv.Strings(array)...)
   556  }
   557  
   558  // Chunk splits an array into multiple arrays,
   559  // the size of each array is determined by `size`.
   560  // The last chunk may contain less than size elements.
   561  func (a *SortedStrArray) Chunk(size int) [][]string {
   562  	if size < 1 {
   563  		return nil
   564  	}
   565  	a.mu.RLock()
   566  	defer a.mu.RUnlock()
   567  	length := len(a.array)
   568  	chunks := int(math.Ceil(float64(length) / float64(size)))
   569  	var n [][]string
   570  	for i, end := 0, 0; chunks > 0; chunks-- {
   571  		end = (i + 1) * size
   572  		if end > length {
   573  			end = length
   574  		}
   575  		n = append(n, a.array[i*size:end])
   576  		i++
   577  	}
   578  	return n
   579  }
   580  
   581  // Rand randomly returns one item from array(no deleting).
   582  func (a *SortedStrArray) Rand() (value string, found bool) {
   583  	a.mu.RLock()
   584  	defer a.mu.RUnlock()
   585  	if len(a.array) == 0 {
   586  		return "", false
   587  	}
   588  	return a.array[grand.Intn(len(a.array))], true
   589  }
   590  
   591  // Rands randomly returns `size` items from array(no deleting).
   592  func (a *SortedStrArray) Rands(size int) []string {
   593  	a.mu.RLock()
   594  	defer a.mu.RUnlock()
   595  	if size <= 0 || len(a.array) == 0 {
   596  		return nil
   597  	}
   598  	array := make([]string, size)
   599  	for i := 0; i < size; i++ {
   600  		array[i] = a.array[grand.Intn(len(a.array))]
   601  	}
   602  	return array
   603  }
   604  
   605  // Join joins array elements with a string `glue`.
   606  func (a *SortedStrArray) Join(glue string) string {
   607  	a.mu.RLock()
   608  	defer a.mu.RUnlock()
   609  	if len(a.array) == 0 {
   610  		return ""
   611  	}
   612  	buffer := bytes.NewBuffer(nil)
   613  	for k, v := range a.array {
   614  		buffer.WriteString(v)
   615  		if k != len(a.array)-1 {
   616  			buffer.WriteString(glue)
   617  		}
   618  	}
   619  	return buffer.String()
   620  }
   621  
   622  // CountValues counts the number of occurrences of all values in the array.
   623  func (a *SortedStrArray) CountValues() map[string]int {
   624  	m := make(map[string]int)
   625  	a.mu.RLock()
   626  	defer a.mu.RUnlock()
   627  	for _, v := range a.array {
   628  		m[v]++
   629  	}
   630  	return m
   631  }
   632  
   633  // Iterator is alias of IteratorAsc.
   634  func (a *SortedStrArray) Iterator(f func(k int, v string) bool) {
   635  	a.IteratorAsc(f)
   636  }
   637  
   638  // IteratorAsc iterates the array readonly in ascending order with given callback function `f`.
   639  // If `f` returns true, then it continues iterating; or false to stop.
   640  func (a *SortedStrArray) IteratorAsc(f func(k int, v string) bool) {
   641  	a.mu.RLock()
   642  	defer a.mu.RUnlock()
   643  	for k, v := range a.array {
   644  		if !f(k, v) {
   645  			break
   646  		}
   647  	}
   648  }
   649  
   650  // IteratorDesc iterates the array readonly in descending order with given callback function `f`.
   651  // If `f` returns true, then it continues iterating; or false to stop.
   652  func (a *SortedStrArray) IteratorDesc(f func(k int, v string) bool) {
   653  	a.mu.RLock()
   654  	defer a.mu.RUnlock()
   655  	for i := len(a.array) - 1; i >= 0; i-- {
   656  		if !f(i, a.array[i]) {
   657  			break
   658  		}
   659  	}
   660  }
   661  
   662  // String returns current array as a string, which implements like json.Marshal does.
   663  func (a *SortedStrArray) String() string {
   664  	if a == nil {
   665  		return ""
   666  	}
   667  	a.mu.RLock()
   668  	defer a.mu.RUnlock()
   669  	buffer := bytes.NewBuffer(nil)
   670  	buffer.WriteByte('[')
   671  	for k, v := range a.array {
   672  		buffer.WriteString(`"` + gstr.QuoteMeta(v, `"\`) + `"`)
   673  		if k != len(a.array)-1 {
   674  			buffer.WriteByte(',')
   675  		}
   676  	}
   677  	buffer.WriteByte(']')
   678  	return buffer.String()
   679  }
   680  
   681  // MarshalJSON implements the interface MarshalJSON for json.Marshal.
   682  // Note that do not use pointer as its receiver here.
   683  func (a SortedStrArray) MarshalJSON() ([]byte, error) {
   684  	a.mu.RLock()
   685  	defer a.mu.RUnlock()
   686  	return json.Marshal(a.array)
   687  }
   688  
   689  // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
   690  func (a *SortedStrArray) UnmarshalJSON(b []byte) error {
   691  	if a.comparator == nil {
   692  		a.array = make([]string, 0)
   693  		a.comparator = defaultComparatorStr
   694  	}
   695  	a.mu.Lock()
   696  	defer a.mu.Unlock()
   697  	if err := json.UnmarshalUseNumber(b, &a.array); err != nil {
   698  		return err
   699  	}
   700  	if a.array != nil {
   701  		sort.Strings(a.array)
   702  	}
   703  	return nil
   704  }
   705  
   706  // UnmarshalValue is an interface implement which sets any type of value for array.
   707  func (a *SortedStrArray) UnmarshalValue(value interface{}) (err error) {
   708  	if a.comparator == nil {
   709  		a.comparator = defaultComparatorStr
   710  	}
   711  	a.mu.Lock()
   712  	defer a.mu.Unlock()
   713  	switch value.(type) {
   714  	case string, []byte:
   715  		err = json.UnmarshalUseNumber(gconv.Bytes(value), &a.array)
   716  	default:
   717  		a.array = gconv.SliceStr(value)
   718  	}
   719  	if a.array != nil {
   720  		sort.Strings(a.array)
   721  	}
   722  	return err
   723  }
   724  
   725  // Filter iterates array and filters elements using custom callback function.
   726  // It removes the element from array if callback function `filter` returns true,
   727  // it or else does nothing and continues iterating.
   728  func (a *SortedStrArray) Filter(filter func(index int, value string) bool) *SortedStrArray {
   729  	a.mu.Lock()
   730  	defer a.mu.Unlock()
   731  	for i := 0; i < len(a.array); {
   732  		if filter(i, a.array[i]) {
   733  			a.array = append(a.array[:i], a.array[i+1:]...)
   734  		} else {
   735  			i++
   736  		}
   737  	}
   738  	return a
   739  }
   740  
   741  // FilterEmpty removes all empty string value of the array.
   742  func (a *SortedStrArray) FilterEmpty() *SortedStrArray {
   743  	a.mu.Lock()
   744  	defer a.mu.Unlock()
   745  	for i := 0; i < len(a.array); {
   746  		if a.array[i] == "" {
   747  			a.array = append(a.array[:i], a.array[i+1:]...)
   748  		} else {
   749  			break
   750  		}
   751  	}
   752  	for i := len(a.array) - 1; i >= 0; {
   753  		if a.array[i] == "" {
   754  			a.array = append(a.array[:i], a.array[i+1:]...)
   755  		} else {
   756  			break
   757  		}
   758  	}
   759  	return a
   760  }
   761  
   762  // Walk applies a user supplied function `f` to every item of array.
   763  func (a *SortedStrArray) Walk(f func(value string) string) *SortedStrArray {
   764  	a.mu.Lock()
   765  	defer a.mu.Unlock()
   766  
   767  	// Keep the array always sorted.
   768  	defer quickSortStr(a.array, a.getComparator())
   769  
   770  	for i, v := range a.array {
   771  		a.array[i] = f(v)
   772  	}
   773  	return a
   774  }
   775  
   776  // IsEmpty checks whether the array is empty.
   777  func (a *SortedStrArray) IsEmpty() bool {
   778  	return a.Len() == 0
   779  }
   780  
   781  // getComparator returns the comparator if it's previously set,
   782  // or else it returns a default comparator.
   783  func (a *SortedStrArray) getComparator() func(a, b string) int {
   784  	if a.comparator == nil {
   785  		return defaultComparatorStr
   786  	}
   787  	return a.comparator
   788  }
   789  
   790  // DeepCopy implements interface for deep copy of current type.
   791  func (a *SortedStrArray) DeepCopy() interface{} {
   792  	if a == nil {
   793  		return nil
   794  	}
   795  	a.mu.RLock()
   796  	defer a.mu.RUnlock()
   797  	newSlice := make([]string, len(a.array))
   798  	copy(newSlice, a.array)
   799  	return NewSortedStrArrayFrom(newSlice, a.mu.IsSafe())
   800  }