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