github.com/enetx/g@v1.0.80/slice.go (about) 1 package g 2 3 import ( 4 "fmt" 5 "reflect" 6 "slices" 7 "strings" 8 9 "github.com/enetx/g/cmp" 10 "github.com/enetx/g/f" 11 "github.com/enetx/g/pkg/rand" 12 ) 13 14 // NewSlice creates a new Slice of the given generic type T with the specified length and 15 // capacity. 16 // The size variadic parameter can have zero, one, or two integer values. 17 // If no values are provided, an empty Slice with a length and capacity of 0 is returned. 18 // If one value is provided, it sets both the length and capacity of the Slice. 19 // If two values are provided, the first value sets the length and the second value sets the 20 // capacity. 21 // 22 // Parameters: 23 // 24 // - size ...Int: A variadic parameter specifying the length and/or capacity of the Slice 25 // 26 // Returns: 27 // 28 // - Slice[T]: A new Slice of the specified generic type T with the given length and capacity 29 // 30 // Example usage: 31 // 32 // s1 := g.NewSlice[int]() // Creates an empty Slice of type int 33 // s2 := g.NewSlice[int](5) // Creates an Slice with length and capacity of 5 34 // s3 := g.NewSlice[int](3, 10) // Creates an Slice with length of 3 and capacity of 10 35 func NewSlice[T any](size ...Int) Slice[T] { 36 var ( 37 length Int 38 capacity Int 39 ) 40 41 switch { 42 case len(size) > 1: 43 length, capacity = size[0], size[1] 44 case len(size) == 1: 45 length, capacity = size[0], size[0] 46 } 47 48 return make(Slice[T], length, capacity) 49 } 50 51 // SliceOf creates a new generic slice containing the provided elements. 52 func SliceOf[T any](slice ...T) Slice[T] { return slice } 53 54 // SliceMap applies the given function to each element of a Slice and returns a new Slice 55 // containing the transformed values. 56 // 57 // Parameters: 58 // 59 // - sl: The input Slice. 60 // 61 // - fn: The function to apply to each element of the input Slice. 62 // 63 // Returns: 64 // 65 // A new Slice containing the results of applying the function to each element of the input Slice. 66 func SliceMap[T, U any](sl Slice[T], fn func(T) U) Slice[U] { return sliceMap(sl.Iter(), fn).Collect() } 67 68 // Iter returns an iterator (SeqSlice[T]) for the Slice, allowing for sequential iteration 69 // over its elements. It is commonly used in combination with higher-order functions, 70 // such as 'ForEach', to perform operations on each element of the Slice. 71 // 72 // Returns: 73 // 74 // A SeqSlice[T], which can be used for sequential iteration over the elements of the Slice. 75 // 76 // Example usage: 77 // 78 // slice := g.Slice[int]{1, 2, 3, 4, 5} 79 // iterator := slice.Iter() 80 // iterator.ForEach(func(element int) { 81 // // Perform some operation on each element 82 // fmt.Println(element) 83 // }) 84 // 85 // The 'Iter' method provides a convenient way to traverse the elements of a Slice 86 // in a functional style, enabling operations like mapping or filtering. 87 func (sl Slice[T]) Iter() SeqSlice[T] { return ToSeqSlice(sl) } 88 89 // AsAny converts each element of the slice to the 'any' type. 90 // It returns a new slice containing the elements as 'any' g.Slice[any]. 91 // 92 // Note: AsAny is useful when you want to work with a slice of a specific type as a slice of 'any'. 93 // It can be particularly handy in conjunction with Flatten to work with nested slices of different types. 94 func (sl Slice[T]) AsAny() Slice[any] { return SliceMap(sl, func(t T) any { return any(t) }) } 95 96 // Fill fills the slice with the specified value. 97 // This function is useful when you want to create an Slice with all elements having the same 98 // value. 99 // This method modifies the original slice in place. 100 // 101 // Parameters: 102 // 103 // - val T: The value to fill the Slice with. 104 // 105 // Returns: 106 // 107 // - Slice[T]: A reference to the original Slice filled with the specified value. 108 // 109 // Example usage: 110 // 111 // slice := g.Slice[int]{0, 0, 0} 112 // slice.Fill(5) 113 // 114 // The modified slice will now contain: 5, 5, 5. 115 func (sl Slice[T]) Fill(val T) { 116 for i := range sl { 117 sl[i] = val 118 } 119 } 120 121 // Index returns the index of the first occurrence of the specified value in the slice, or -1 if 122 // not found. 123 func (sl Slice[T]) Index(val T) Int { 124 switch s := any(sl).(type) { 125 case Slice[Int]: 126 return Int(slices.Index(s, any(val).(Int))) 127 case Slice[String]: 128 return Int(slices.Index(s, any(val).(String))) 129 case Slice[Float]: 130 return Int(slices.Index(s, any(val).(Float))) 131 case Slice[string]: 132 return Int(slices.Index(s, any(val).(string))) 133 case Slice[bool]: 134 return Int(slices.Index(s, any(val).(bool))) 135 case Slice[int]: 136 return Int(slices.Index(s, any(val).(int))) 137 case Slice[int8]: 138 return Int(slices.Index(s, any(val).(int8))) 139 case Slice[int16]: 140 return Int(Int(slices.Index(s, any(val).(int16)))) 141 case Slice[int32]: 142 return Int(slices.Index(s, any(val).(int32))) 143 case Slice[int64]: 144 return Int(slices.Index(s, any(val).(int64))) 145 case Slice[uint]: 146 return Int(slices.Index(s, any(val).(uint))) 147 case Slice[uint8]: 148 return Int(slices.Index(s, any(val).(uint8))) 149 case Slice[uint16]: 150 return Int(slices.Index(s, any(val).(uint16))) 151 case Slice[uint32]: 152 return Int(slices.Index(s, any(val).(uint32))) 153 case Slice[uint64]: 154 return Int(slices.Index(s, any(val).(uint64))) 155 case Slice[float32]: 156 return Int(slices.Index(s, any(val).(float32))) 157 case Slice[float64]: 158 return Int(slices.Index(s, any(val).(float64))) 159 default: 160 return sl.IndexBy(f.Eqd(val)) 161 } 162 } 163 164 // IndexBy returns the index of the first element in the slice 165 // satisfying the custom comparison function provided by the user. 166 // It iterates through the slice and applies the comparison function to each element and the target value. 167 // If the comparison function returns true for any pair of elements, it returns the index of that element. 168 // If no such element is found, it returns -1. 169 func (sl Slice[T]) IndexBy(fn func(t T) bool) Int { return Int(slices.IndexFunc(sl, fn)) } 170 171 // RandomSample returns a new slice containing a random sample of elements from the original slice. 172 // The sampling is done without replacement, meaning that each element can only appear once in the result. 173 // 174 // Parameters: 175 // 176 // - sequence int: The number of unique elements to include in the random sample. 177 // 178 // Returns: 179 // 180 // - Slice[T]: A new Slice containing the random sample of unique elements. 181 // 182 // Example usage: 183 // 184 // slice := g.Slice[int]{1, 2, 3, 4, 5, 6, 7, 8, 9} 185 // sample := slice.RandomSample(3) 186 // 187 // The resulting sample will contain 3 unique elements randomly selected from the original slice. 188 func (sl Slice[T]) RandomSample(sequence Int) Slice[T] { 189 if sequence.Gte(sl.Len()) { 190 return sl 191 } 192 193 clone := sl.Clone() 194 clone.Shuffle() 195 196 return clone[0:sequence] 197 } 198 199 // RandomRange returns a new slice containing a random sample of elements from a subrange of the original slice. 200 // The sampling is done without replacement, meaning that each element can only appear once in the result. 201 func (sl Slice[T]) RandomRange(from, to Int) Slice[T] { 202 if from < 0 { 203 from = 0 204 } 205 206 if to < 0 || to > sl.Len() { 207 to = sl.Len() 208 } 209 210 if from > to { 211 from = to 212 } 213 214 return sl.RandomSample(from.RandomRange(to)) 215 } 216 217 // Insert inserts values at the specified index in the slice and returns the resulting slice. 218 // The original slice remains unchanged. 219 // 220 // Parameters: 221 // 222 // - i Int: The index at which to insert the new values. 223 // 224 // - values ...T: A variadic list of values to insert at the specified index. 225 // 226 // Returns: 227 // 228 // - Slice[T]: A new Slice containing the original elements and the inserted values. 229 // 230 // Example usage: 231 // 232 // slice := g.Slice[string]{"a", "b", "c", "d"} 233 // newSlice := slice.Insert(2, "e", "f") 234 // 235 // The resulting newSlice will be: ["a", "b", "e", "f", "c", "d"]. 236 func (sl Slice[T]) Insert(i Int, values ...T) Slice[T] { return sl.Replace(i, i, values...) } 237 238 // InsertInPlace inserts values at the specified index in the slice and modifies the original 239 // slice. 240 // 241 // Parameters: 242 // 243 // - i Int: The index at which to insert the new values. 244 // 245 // - values ...T: A variadic list of values to insert at the specified index. 246 // 247 // Example usage: 248 // 249 // slice := g.Slice[string]{"a", "b", "c", "d"} 250 // slice.InsertInPlace(2, "e", "f") 251 // 252 // The resulting slice will be: ["a", "b", "e", "f", "c", "d"]. 253 func (sl *Slice[T]) InsertInPlace(i Int, values ...T) { sl.ReplaceInPlace(i, i, values...) } 254 255 // Replace replaces the elements of sl[i:j] with the given values, and returns 256 // a new slice with the modifications. The original slice remains unchanged. 257 // Replace panics if sl[i:j] is not a valid slice of sl. 258 // 259 // Parameters: 260 // 261 // - i Int: The starting index of the slice to be replaced. 262 // 263 // - j Int: The ending index of the slice to be replaced. 264 // 265 // - values ...T: A variadic list of values to replace the existing slice. 266 // 267 // Returns: 268 // 269 // - Slice[T]: A new Slice containing the original elements with the specified elements replaced. 270 // 271 // Example usage: 272 // 273 // slice := g.Slice[string]{"a", "b", "c", "d"} 274 // newSlice := slice.Replace(1, 3, "e", "f") 275 // 276 // The original slice remains ["a", "b", "c", "d"], and the newSlice will be: ["a", "e", "f", "d"]. 277 func (sl Slice[T]) Replace(i, j Int, values ...T) Slice[T] { 278 i = sl.bound(i) 279 j = sl.bound(j) 280 281 if i > j { 282 return NewSlice[T]() 283 } 284 285 total := sl[:i].Len() + Int(len(values)) + sl[j:].Len() 286 slice := NewSlice[T](total) 287 288 copy(slice, sl[:i]) 289 copy(slice[i:], values) 290 copy(slice[i+Int(len(values)):], sl[j:]) 291 292 return slice 293 } 294 295 // ReplaceInPlace replaces the elements of sl[i:j] with the given values, 296 // and modifies the original slice in place. ReplaceInPlace panics if sl[i:j] 297 // is not a valid slice of sl. 298 // 299 // Parameters: 300 // 301 // - i int: The starting index of the slice to be replaced. 302 // 303 // - j int: The ending index of the slice to be replaced. 304 // 305 // - values ...T: A variadic list of values to replace the existing slice. 306 // 307 // Example usage: 308 // 309 // slice := g.Slice[string]{"a", "b", "c", "d"} 310 // slice.ReplaceInPlace(1, 3, "e", "f") 311 // 312 // After the ReplaceInPlace operation, the resulting slice will be: ["a", "e", "f", "d"]. 313 func (sl *Slice[T]) ReplaceInPlace(i, j Int, values ...T) { 314 i = sl.bound(i) 315 j = sl.bound(j) 316 317 if i > j { 318 *sl = (*sl)[:0] 319 return 320 } 321 322 if i == j { 323 if len(values) > 0 { 324 *sl = append((*sl)[:i], append(values, (*sl)[i:]...)...) 325 } 326 327 return 328 } 329 330 diff := Int(len(values)) - (j - i) 331 332 if diff > 0 { 333 *sl = append(*sl, NewSlice[T](diff)...) 334 } 335 336 copy((*sl)[i+Int(len(values)):], (*sl)[j:]) 337 copy((*sl)[i:], values) 338 339 if diff < 0 { 340 *sl = (*sl)[:(*sl).Len()+diff] 341 } 342 } 343 344 // AddUnique appends unique elements from the provided arguments to the current slice. 345 // 346 // The function iterates over the provided elements and checks if they are already present 347 // in the slice. If an element is not already present, it is appended to the slice. The 348 // resulting slice is returned, containing the unique elements from both the original 349 // slice and the provided elements. 350 // 351 // Parameters: 352 // 353 // - elems (...T): A variadic list of elements to be appended to the slice. 354 // 355 // Returns: 356 // 357 // - Slice[T]: A new slice containing the unique elements from both the original slice 358 // and the provided elements. 359 // 360 // Example usage: 361 // 362 // slice := g.Slice[int]{1, 2, 3, 4, 5} 363 // slice = slice.AddUnique(3, 4, 5, 6, 7) 364 // fmt.Println(slice) 365 // 366 // Output: [1 2 3 4 5 6 7]. 367 func (sl Slice[T]) AddUnique(elems ...T) Slice[T] { 368 for _, elem := range elems { 369 if !sl.Contains(elem) { 370 sl = append(sl, elem) 371 } 372 } 373 374 return sl 375 } 376 377 // AddUniqueInPlace appends unique elements from the provided arguments to the current slice. 378 // 379 // The function iterates over the provided elements and checks if they are already present 380 // in the slice. If an element is not already present, it is appended to the slice. 381 // 382 // Parameters: 383 // 384 // - elems (...T): A variadic list of elements to be appended to the slice. 385 // 386 // Example usage: 387 // 388 // slice := g.Slice[int]{1, 2, 3, 4, 5} 389 // slice.AddUniqueInPlace(3, 4, 5, 6, 7) 390 // fmt.Println(slice) 391 // 392 // Output: [1 2 3 4 5 6 7]. 393 func (sl *Slice[T]) AddUniqueInPlace(elems ...T) { 394 for _, elem := range elems { 395 if !sl.Contains(elem) { 396 *sl = append(*sl, elem) 397 } 398 } 399 } 400 401 // Get returns the element at the given index, handling negative indices as counting from the end 402 // of the slice. 403 func (sl Slice[T]) Get(index Int) T { return sl[sl.bound(index)] } 404 405 // Shuffle shuffles the elements in the slice randomly. 406 // This method modifies the original slice in place. 407 // 408 // The function uses the crypto/rand package to generate random indices. 409 // 410 // Example usage: 411 // 412 // slice := g.Slice[int]{1, 2, 3, 4, 5} 413 // slice.Shuffle() 414 // fmt.Println(slice) 415 // 416 // Output: A randomly shuffled version of the original slice, e.g., [4 1 5 2 3]. 417 func (sl Slice[T]) Shuffle() { 418 n := sl.Len() 419 420 for i := n - 1; i > 0; i-- { 421 j := rand.N(i + 1) 422 sl.swap(i, j) 423 } 424 } 425 426 // Reverse reverses the order of the elements in the slice. 427 // This method modifies the original slice in place. 428 // 429 // Returns: 430 // 431 // - Slice[T]: The modified slice with the elements reversed. 432 // 433 // Example usage: 434 // 435 // slice := g.Slice[int]{1, 2, 3, 4, 5} 436 // slice.Reverse() 437 // fmt.Println(slice) 438 // 439 // Output: [5 4 3 2 1]. 440 func (sl Slice[T]) Reverse() { slices.Reverse(sl) } 441 442 // SortBy sorts the elements in the slice using the provided comparison function. 443 // It modifies the original slice in place. It requires the elements to be of a type 444 // that is comparable. 445 // 446 // The function takes a custom comparison function as an argument and sorts the elements 447 // of the slice using the provided logic. The comparison function should return true if 448 // the element at index i should come before the element at index j, and false otherwise. 449 // 450 // Parameters: 451 // 452 // - f func(a, b T) cmp.Ordered: A comparison function that takes two indices i and j and returns a bool. 453 // 454 // Example usage: 455 // 456 // sl := NewSlice[int](1, 5, 3, 2, 4) 457 // sl.SortBy(func(a, b int) cmp.Ordering { return cmp.Cmp(a, b) }) // sorts in ascending order. 458 func (sl Slice[T]) SortBy(fn func(a, b T) cmp.Ordering) { 459 slices.SortFunc(sl, func(a, b T) int { return int(fn(a, b)) }) 460 } 461 462 // ToStringSlice converts the Slice into a slice of strings. 463 func (sl Slice[T]) ToStringSlice() []string { 464 result := make([]string, 0, len(sl)) 465 466 for _, v := range sl { 467 result = append(result, fmt.Sprint(v)) 468 } 469 470 return result 471 } 472 473 // Join joins the elements in the slice into a single String, separated by the provided separator 474 // (if any). 475 func (sl Slice[T]) Join(sep ...T) String { 476 var separator string 477 if len(sep) != 0 { 478 separator = fmt.Sprint(sep[0]) 479 } 480 481 return String(strings.Join(sl.ToStringSlice(), separator)) 482 } 483 484 // SubSlice returns a new slice containing elements from the current slice between the specified start 485 // and end indices, with an optional step parameter to define the increment between elements. 486 // The function checks if the start and end indices are within the bounds of the original slice. 487 // If the end index is negative, it represents the position from the end of the slice. 488 // If the start index is negative, it represents the position from the end of the slice counted 489 // from the start index. 490 // 491 // Parameters: 492 // 493 // - start (Int): The start index of the range. 494 // 495 // - end (Int): The end index of the range. 496 // 497 // - step (Int, optional): The increment between elements. Defaults to 1 if not provided. 498 // If negative, the slice is traversed in reverse order. 499 // 500 // Returns: 501 // 502 // - Slice[T]: A new slice containing elements from the current slice between the start and end 503 // indices, with the specified step. 504 // 505 // Example usage: 506 // 507 // slice := g.Slice[int]{1, 2, 3, 4, 5, 6, 7, 8, 9} 508 // subSlice := slice.SubSlice(1, 7, 2) // Extracts elements 2, 4, 6 509 // fmt.Println(subSlice) 510 // 511 // Output: [2 4 6]. 512 func (sl Slice[T]) SubSlice(start, end Int, step ...Int) Slice[T] { 513 _step := Int(1) 514 515 if len(step) != 0 { 516 _step = step[0] 517 } 518 519 start = sl.bound(start, struct{}{}) 520 end = sl.bound(end, struct{}{}) 521 522 if (start >= end && _step > 0) || (start <= end && _step < 0) || _step == 0 { 523 return NewSlice[T]() 524 } 525 526 var loopCondition func(Int) bool 527 if _step > 0 { 528 loopCondition = func(i Int) bool { return i < end } 529 } else { 530 loopCondition = func(i Int) bool { return i > end } 531 } 532 533 var slice Slice[T] 534 535 for i := start; loopCondition(i); i += _step { 536 slice = append(slice, sl[i]) 537 } 538 539 return slice 540 } 541 542 // Cut removes a range of elements from the Slice and returns a new Slice. 543 // It creates two slices: one from the beginning of the original slice up to 544 // the specified start index (exclusive), and another from the specified end 545 // index (inclusive) to the end of the original slice. These two slices are 546 // then concatenated to form the resulting Slice. 547 // 548 // Parameters: 549 // 550 // - start (Int): The start index of the range to be removed. 551 // 552 // - end (Int): The end index of the range to be removed. 553 // 554 // Note: 555 // 556 // The function also supports negative indices. Negative indices are counted 557 // from the end of the slice. For example, -1 means the last element, -2 558 // means the second-to-last element, and so on. 559 // 560 // Returns: 561 // 562 // Slice[T]: A new slice containing elements from the current slice with 563 // the specified range removed. 564 // 565 // Example: 566 // 567 // slice := g.Slice[int]{1, 2, 3, 4, 5} 568 // newSlice := slice.Cut(1, 3) 569 // // newSlice is [1 4 5] 570 func (sl Slice[T]) Cut(start, end Int) Slice[T] { return sl.Replace(start, end) } 571 572 // CutInPlace removes a range of elements from the Slice in-place. 573 // It modifies the original slice by creating two slices: one from the 574 // beginning of the original slice up to the specified start index 575 // (exclusive), and another from the specified end index (inclusive) 576 // to the end of the original slice. These two slices are then 577 // concatenated to form the modified original Slice. 578 // 579 // Parameters: 580 // 581 // - start (Int): The start index of the range to be removed. 582 // 583 // - end (Int): The end index of the range to be removed. 584 // 585 // Note: 586 // 587 // The function also supports negative indices. Negative indices are counted 588 // from the end of the slice. For example, -1 means the last element, -2 589 // means the second-to-last element, and so on. 590 func (sl *Slice[T]) CutInPlace(start, end Int) { sl.ReplaceInPlace(start, end) } 591 592 // Random returns a random element from the slice. 593 // 594 // The function uses the crypto/rand package to generate a random index within the bounds of the 595 // slice. If the slice is empty, the zero value of type T is returned. 596 // 597 // Returns: 598 // 599 // - T: A random element from the slice. 600 // 601 // Example usage: 602 // 603 // slice := g.Slice[int]{1, 2, 3, 4, 5} 604 // randomElement := slice.Random() 605 // fmt.Println(randomElement) 606 // 607 // Output: <any random element from the slice>. 608 func (sl Slice[T]) Random() T { 609 if sl.Empty() { 610 return *new(T) 611 } 612 613 return sl[rand.N(sl.Len())] 614 } 615 616 // Clone returns a copy of the slice. 617 func (sl Slice[T]) Clone() Slice[T] { return slices.Clone(sl) } 618 619 // LastIndex returns the last index of the slice. 620 func (sl Slice[T]) LastIndex() Int { 621 if sl.NotEmpty() { 622 return sl.Len() - 1 623 } 624 625 return 0 626 } 627 628 // Eq returns true if the slice is equal to the provided other slice. 629 func (sl Slice[T]) Eq(other Slice[T]) bool { 630 switch o := any(other).(type) { 631 case Slice[Int]: 632 return slices.Equal(any(sl).(Slice[Int]), o) 633 case Slice[String]: 634 return slices.Equal(any(sl).(Slice[String]), o) 635 case Slice[Float]: 636 return slices.Equal(any(sl).(Slice[Float]), o) 637 case Slice[int]: 638 return slices.Equal(any(sl).(Slice[int]), o) 639 case Slice[string]: 640 return slices.Equal(any(sl).(Slice[string]), o) 641 case Slice[bool]: 642 return slices.Equal(any(sl).(Slice[bool]), o) 643 case Slice[int8]: 644 return slices.Equal(any(sl).(Slice[int8]), o) 645 case Slice[int16]: 646 return slices.Equal(any(sl).(Slice[int16]), o) 647 case Slice[int32]: 648 return slices.Equal(any(sl).(Slice[int32]), o) 649 case Slice[int64]: 650 return slices.Equal(any(sl).(Slice[int64]), o) 651 case Slice[uint]: 652 return slices.Equal(any(sl).(Slice[uint]), o) 653 case Slice[uint8]: 654 return slices.Equal(any(sl).(Slice[uint8]), o) 655 case Slice[uint16]: 656 return slices.Equal(any(sl).(Slice[uint16]), o) 657 case Slice[uint32]: 658 return slices.Equal(any(sl).(Slice[uint32]), o) 659 case Slice[uint64]: 660 return slices.Equal(any(sl).(Slice[uint64]), o) 661 case Slice[float32]: 662 return slices.Equal(any(sl).(Slice[float32]), o) 663 case Slice[float64]: 664 return slices.Equal(any(sl).(Slice[float64]), o) 665 default: 666 return sl.EqBy(other, func(x, y T) bool { return reflect.DeepEqual(x, y) }) 667 } 668 } 669 670 // EqBy reports whether two slices are equal using an equality 671 // function on each pair of elements. If the lengths are different, 672 // EqBy returns false. Otherwise, the elements are compared in 673 // increasing index order, and the comparison stops at the first index 674 // for which eq returns false. 675 func (sl Slice[T]) EqBy(other Slice[T], fn func(x, y T) bool) bool { 676 return slices.EqualFunc(sl, other, fn) 677 } 678 679 // String returns a string representation of the slice. 680 func (sl Slice[T]) String() string { 681 builder := NewBuilder() 682 683 for _, v := range sl { 684 builder.Write(Sprintf("%v, ", v)) 685 } 686 687 return builder.String().TrimRight(", ").Format("Slice[%s]").Std() 688 } 689 690 // Append appends the provided elements to the slice and returns the modified slice. 691 func (sl Slice[T]) Append(elems ...T) Slice[T] { return append(sl, elems...) } 692 693 // AppendInPlace appends the provided elements to the slice and modifies the original slice. 694 func (sl *Slice[T]) AppendInPlace(elems ...T) { *sl = append(*sl, elems...) } 695 696 // Cap returns the capacity of the Slice. 697 func (sl Slice[T]) Cap() Int { return Int(cap(sl)) } 698 699 // Contains returns true if the slice contains the provided value. 700 func (sl Slice[T]) Contains(val T) bool { return sl.Index(val) >= 0 } 701 702 // ContainsBy returns true if the slice contains an element that satisfies the provided function fn, false otherwise. 703 func (sl Slice[T]) ContainsBy(fn func(t T) bool) bool { return sl.IndexBy(fn) >= 0 } 704 705 // ContainsAny checks if the Slice contains any element from another Slice. 706 func (sl Slice[T]) ContainsAny(values ...T) bool { 707 if sl.Empty() || len(values) == 0 { 708 return false 709 } 710 711 for _, v := range values { 712 if sl.Contains(v) { 713 return true 714 } 715 } 716 717 return false 718 } 719 720 // ContainsAll checks if the Slice contains all elements from another Slice. 721 func (sl Slice[T]) ContainsAll(values ...T) bool { 722 if sl.Empty() || len(values) == 0 { 723 return false 724 } 725 726 for _, v := range values { 727 if !sl.Contains(v) { 728 return false 729 } 730 } 731 732 return true 733 } 734 735 // Delete removes the element at the specified index from the slice and returns the modified slice. 736 func (sl Slice[T]) Delete(i Int) Slice[T] { 737 nsl := sl.Clone() 738 nsl.DeleteInPlace(i) 739 740 return nsl.Clip() 741 } 742 743 // DeleteInPlace removes the element at the specified index from the slice and modifies the 744 // original slice. 745 func (sl *Slice[T]) DeleteInPlace(i Int) { 746 i = sl.bound(i) 747 copy((*sl)[i:], (*sl)[i+1:]) 748 *sl = (*sl)[:len(*sl)-1] 749 } 750 751 // Empty returns true if the slice is empty. 752 func (sl Slice[T]) Empty() bool { return len(sl) == 0 } 753 754 // Last returns the last element of the slice. 755 func (sl Slice[T]) Last() T { return sl.Get(-1) } 756 757 // Ne returns true if the slice is not equal to the provided other slice. 758 func (sl Slice[T]) Ne(other Slice[T]) bool { return !sl.Eq(other) } 759 760 // NeBy reports whether two slices are not equal using an inequality 761 // function on each pair of elements. If the lengths are different, 762 // NeBy returns true. Otherwise, the elements are compared in 763 // increasing index order, and the comparison stops at the first index 764 // for which fn returns true. 765 func (sl Slice[T]) NeBy(other Slice[T], fn func(x, y T) bool) bool { return !sl.EqBy(other, fn) } 766 767 // NotEmpty returns true if the slice is not empty. 768 func (sl Slice[T]) NotEmpty() bool { return !sl.Empty() } 769 770 // Pop returns the last element of the slice and a new slice without the last element. 771 func (sl Slice[T]) Pop() (T, Slice[T]) { return sl.Last(), sl.SubSlice(0, -1) } 772 773 // Set sets the value at the specified index in the slice and returns the modified slice. 774 // This method modifies the original slice in place. 775 // 776 // Parameters: 777 // 778 // - index (Int): The index at which to set the new value. 779 // 780 // - val (T): The new value to be set at the specified index. 781 // 782 // Returns: 783 // 784 // - Slice[T]: The modified slice with the new value set at the specified index. 785 // 786 // Example usage: 787 // 788 // slice := g.Slice[int]{1, 2, 3, 4, 5} 789 // slice.Set(2, 99) 790 // fmt.Println(slice) 791 // 792 // Output: [1 2 99 4 5]. 793 func (sl Slice[T]) Set(index Int, val T) { sl[sl.bound(index)] = val } 794 795 // Len returns the length of the slice. 796 func (sl Slice[T]) Len() Int { return Int(len(sl)) } 797 798 // Swap swaps the elements at the specified indices in the slice. 799 // This method modifies the original slice in place. 800 // 801 // Parameters: 802 // 803 // - i (Int): The index of the first element to be swapped. 804 // 805 // - j (Int): The index of the second element to be swapped. 806 // 807 // Returns: 808 // 809 // - Slice[T]: The modified slice with the elements at the specified indices swapped. 810 // 811 // Example usage: 812 // 813 // slice := g.Slice[int]{1, 2, 3, 4, 5} 814 // slice.Swap(1, 3) 815 // fmt.Println(slice) 816 // 817 // Output: [1 4 3 2 5]. 818 func (sl Slice[T]) Swap(i, j Int) { 819 i = sl.bound(i) 820 j = sl.bound(j) 821 822 sl.swap(i, j) 823 } 824 825 func (sl Slice[T]) swap(i, j Int) { sl[i], sl[j] = sl[j], sl[i] } 826 827 // Grow increases the slice's capacity, if necessary, to guarantee space for 828 // another n elements. After Grow(n), at least n elements can be appended 829 // to the slice without another allocation. If n is negative or too large to 830 // allocate the memory, Grow panics. 831 func (sl Slice[T]) Grow(n Int) Slice[T] { return slices.Grow(sl, n.Std()) } 832 833 // Clip removes unused capacity from the slice. 834 func (sl Slice[T]) Clip() Slice[T] { return slices.Clip(sl) } 835 836 // Std returns a new slice with the same elements as the Slice[T]. 837 func (sl Slice[T]) Std() []T { return sl } 838 839 // Print prints the elements of the Slice to the standard output (console) 840 // and returns the Slice unchanged. 841 func (sl Slice[T]) Print() Slice[T] { fmt.Println(sl); return sl } 842 843 // Unpack assigns values of the slice's elements to the variables passed as pointers. 844 // If the number of variables passed is greater than the length of the slice, 845 // the function ignores the extra variables. 846 // 847 // Parameters: 848 // 849 // - vars (...*T): Pointers to variables where the values of the slice's elements will be stored. 850 // 851 // Example: 852 // 853 // slice := g.Slice[int]{1, 2, 3, 4, 5} 854 // var a, b, c int 855 // slice.Unpack(&a, &b, &c) 856 // fmt.Println(a, b, c) // Output: 1 2 3 857 func (sl Slice[T]) Unpack(vars ...*T) { 858 if len(vars) > len(sl) { 859 vars = vars[:len(sl)] 860 } 861 862 for i, v := range vars { 863 *v = sl[i] 864 } 865 } 866 867 // MaxBy returns the maximum value in the slice according to the provided comparison function fn. 868 // It applies fn pairwise to the elements of the slice until it finds the maximum value. 869 // It returns the maximum value found. 870 // 871 // Example: 872 // 873 // s := Slice[int]{3, 1, 4, 2, 5} 874 // maxInt := s.MaxBy(cmp.Cmp) 875 // fmt.Println(maxInt) // Output: 5 876 func (sl Slice[T]) MaxBy(fn func(a, b T) cmp.Ordering) T { return cmp.MaxBy(fn, sl...) } 877 878 // MinBy returns the minimum value in the slice according to the provided comparison function fn. 879 // It applies fn pairwise to the elements of the slice until it finds the minimum value. 880 // It returns the minimum value found. 881 // 882 // Example: 883 // 884 // s := Slice[int]{3, 1, 4, 2, 5} 885 // minInt := s.MinBy(cmp.Cmp) 886 // fmt.Println(minInt) // Output: 1 887 func (sl Slice[T]) MinBy(fn func(a, b T) cmp.Ordering) T { return cmp.MinBy(fn, sl...) } 888 889 func (sl Slice[T]) bound(i Int, subslice ...struct{}) Int { 890 ii := i 891 if ii < 0 { 892 ii += sl.Len() 893 } 894 895 var negative Int 896 if len(subslice) != 0 { 897 negative = -1 898 } 899 900 if ii > sl.Len() || ii < negative { 901 panic(fmt.Sprintf("runtime error: slice bounds out of range [%d] with length %d", i, len(sl))) 902 } 903 904 return ii 905 }