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