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