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