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