From a5273e97b1a04eb0cdc55c70dbc96c39bd878dad Mon Sep 17 00:00:00 2001 From: Linneeeeeeee Date: Fri, 20 Oct 2023 16:48:30 +1100 Subject: [PATCH] Dev (#48) * Dev --- README.md | 211 +++-- benchmark_test.go | 543 +++++++++++- doc.go | 2 +- example_test.go | 78 +- slice.go | 853 +++++-------------- slice_test.go | 2062 ++++++++++++++++----------------------------- 6 files changed, 1605 insertions(+), 2144 deletions(-) diff --git a/README.md b/README.md index a381b2b..afbc2fe 100644 --- a/README.md +++ b/README.md @@ -46,31 +46,31 @@ Provided methods for `&slice.Slice[T]`. Appends values to the end of the slice and returns a pointer to the modified slice. ```Go s := &slice.Slice[int]{1, 2, 3} -s.Append(4, 5) // s is now [1, 2, 3, 4, 5] +s.Append(4, 5) // s is now [1, 2, 3, 4, 5]. ``` ### AppendFunc Appends selected elements to the end of the slice based on a provided condition. ```Go s := &slice.Slice[int]{} -s.AppendFunc(func(i int, value int) bool { +s.AppendFunc([]int{1, 2, 3, 4, 5}, func(i int, value int) bool { return value%2 == 0 // Append even numbers to the Slice. -}, 1, 2, 3, 4, 5) +}) ``` ### AppendLength Appends values to the end of the slice and returns the length of the modified slice. ```Go s := &slice.Slice[int]{1, 2, 3} -length := s.AppendLength(4, 5) // s is now [1, 2, 3, 4, 5], length is 5 +length := s.AppendLength(4, 5) // s is now [1, 2, 3, 4, 5], length is 5. ``` ### Bounds Checks if an index is within the valid range of indices for the slice. ```Go s := &slice.Slice[int]{1, 2, 3} -inBounds := s.Bounds(1) // inBounds is true -outOfBounds := s.Bounds(5) // outOfBounds is false +inBounds := s.Bounds(1) // inBounds is true. +outOfBounds := s.Bounds(5) // outOfBounds is false. ``` ### Clone @@ -78,7 +78,7 @@ Creates a duplicate of the current slice with a reference to a new pointer. ```Go s1 := &slice.Slice[int]{1, 2} s2 := s1.Clone() -s2.Replace(0, 3) // s1 is still [1, 2], s2 is [3, 2] +s2.Replace(0, 3) // s1 is still [1, 2], s2 is [3, 2]. ``` ### Concatenate @@ -86,7 +86,7 @@ Merges elements from another slice to the tail of the receiver slice. ```Go s1 := &slice.Slice[int]{1, 2, 3} s2 := &slice.Slice[int]{4, 5} -s1.Concatenate(s2) // s1 is now [1, 2, 3, 4, 5] +s1.Concatenate(s2) // s1 is now [1, 2, 3, 4, 5]. ``` ### ConcatenateFunc @@ -96,7 +96,7 @@ s1 := &slice.Slice[int]{1, 2, 3} s2 := &slice.Slice[int]{4, 5, 6} s1.ConcatenateFunc(s2, func(i int, value int) bool { return value%2 == 0 -}) // s1 is now [1, 2, 3, 4, 6] +}) // s1 is now [1, 2, 3, 4, 6]. ``` ### ConcatenateLength @@ -104,28 +104,28 @@ Merges elements from another slice to the tail of the receiver slice and returns ```Go s1 := &slice.Slice[int]{1, 2, 3} s2 := &slice.Slice[int]{4, 5} -length := s1.ConcatenateLength(s2) // s1 is now [1, 2, 3, 4, 5], length is 5 +length := s1.ConcatenateLength(s2) // s1 is now [1, 2, 3, 4, 5], length is 5. ``` ### Contains Checks if a value exists in the slice. ```Go s := &slice.Slice[string]{"apple", "banana", "cherry"} -containsBanana := s.Contains("banana") // containsBanana is true +containsBanana := s.Contains("banana") // containsBanana is true. ``` ### ContainsMany Checks if multiple values exist in the slice and returns a boolean slice indicating their presence. ```Go s := &slice.Slice[int]{1, 2, 3, 4, 5} -result := s.ContainsMany(2, 4, 6) // result will be [true, true, false] +result := s.ContainsMany(2, 4, 6) // result will be [true, true, false]. ``` ### Delete Safely removes an element from the slice by index. ```Go s := &slice.Slice[int]{1, 2, 3, 4, 5} -s.Delete(2) // s is now [1, 2, 4, 5] +s.Delete(2) // s is now [1, 2, 4, 5]. ``` ### DeleteFunc @@ -140,14 +140,14 @@ s.DeleteFunc(even) // 's' will contain [1, 3, 5] after removing even elements. Safely removes an element from the slice by index and returns the new length of the modified slice. ```Go s := &slice.Slice[int]{1, 2, 3, 4, 5} -newLength := s.DeleteLength(2) // s is now [1, 2, 4, 5], newLength is 4 +newLength := s.DeleteLength(2) // s is now [1, 2, 4, 5], newLength is 4. ``` ### DeleteOK Safely removes an element from the slice by index and returns a boolean indicating the success of the operation. ```Go s := &slice.Slice[int]{1, 2, 3, 4, 5} -deleted := s.DeleteOK(2) // s is now [1, 2, 4, 5], deleted is true +deleted := s.DeleteOK(2) // s is now [1, 2, 4, 5], deleted is true. ``` ### DeleteUnsafe @@ -163,7 +163,7 @@ Executes a provided function for each element in the slice. ```Go s := &slice.Slice[string]{"apple", "banana", "cherry"} s.Each(func(i int, value string) { - fmt.Printf("Element %d: %s\n", i, value) + fmt.Printf("Element %d: %s\n", i, value) // i will be "1", value will be "apple", and so on. }) ``` @@ -173,16 +173,26 @@ Executes a provided function for each element in the slice with an optional brea s := &slice.Slice[int]{1, 2, 3, 4, 5} s.EachBreak(func(i int, value int) bool { fmt.Printf("Element %d: %d\n", i, value) - return i < 3 // Stop iteration when i is less than 3 + return i < 3 // Stop iteration when i is less than 3. }) ``` +### EachOK +Executes a provided function for each element in the slice and returns a bool breaking the loop when true. +```Go +s := &slice.Slice[int]{1, 2, 3, 4, 5} +result := slice.EachOK(func(i int, value int) bool { + fmt.Println(i, value) + return value == 4 // Stop iteration at index 3. +}) // result is true. +``` + ### EachReverse Executes a provided function for each element in reverse order. ```Go s := &slice.Slice[int]{1, 2, 3, 4, 5} s.EachReverse(func(i int, value int) { - fmt.Printf("Element %d: %d\n", i, value) + fmt.Printf("Element %d: %d\n", i, value) // first iteration i will be 4, value will be 5. }) ``` @@ -192,16 +202,26 @@ Executes a provided function for each element in reverse order with an optional s := &slice.Slice[int]{1, 2, 3, 4, 5} s.EachReverseBreak(func(i int, value int) bool { fmt.Printf("Element %d: %d\n", i, value) - return i > 2 // Stop iteration when i is greater than 2 + return i > 2 // Stop iteration when i is greater than 2. }) ``` +### EachReverseOK +Executes a provided function for each element in the slice and returns a bool breaking the loop when true. +```Go +s := &slice.Slice[int]{1, 2, 3, 4, 5} +result := slice.EachReverseOK(func(i int, value int) bool { + fmt.Println(i, value) + return value == 4 // Stop iteration at index 3 (runs two loops). +}) // result is true. +``` + ### Equal Checks if the two slices are equal. ```Go s1 := slice.Slice[int]{1, 2, 3} s2 := slice.Slice[int]{1, 2, 3} -equal := s1.Equal(s2) // true +equal := s1.Equal(s2) // true. ``` ### EqualFunc @@ -215,6 +235,14 @@ customEqual := func(i int, value1, value2 int) bool { equal := s1.EqualFunc(s2, customEqual) // true. ``` +### EqualLength +Checks if the two slices have the same length. +```Go +s1 := slice.Slice[int]{1, 2, 3} +s2 := slice.Slice[int]{2, 4, 6} +equal := s1.Length(s2) // true. +``` + ### Fetch Retrieves the element at a specified index in the slice. ```Go @@ -227,8 +255,8 @@ Retrieves the element at a specified index in the slice and the length of the sl ```Go s := &slice.Slice[int]{10, 20, 30, 40, 50} value, length := s.FetchLength(2) -// value will be 30 -// length will be 5 +// value will be 30. +// length will be 5. ``` ### Filter @@ -237,7 +265,7 @@ Creates a new slice containing elements that satisfy a given predicate function. s := &slice.Slice[int]{1, 2, 3, 4, 5} filtered := s.Filter(func(x int) bool { return x%2 == 0 Keep only even numbers -}) // filtered will be &Slice[int]{2, 4} +}) // filtered will be &Slice[int]{2, 4}. ``` ### FindIndex @@ -247,8 +275,8 @@ s := &slice.Slice[string]{"apple", "banana", "cherry"} index, found := s.FindIndex(func(fruit string) bool { return fruit == "banana" }) -// index will be 1 -// found will be true +// index will be 1. +// found will be true. ``` ### Get @@ -256,78 +284,78 @@ Retrieves the element at a specified index in the slice and returns a boolean in ```Go s := &slice.Slice[float64]{3.14, 2.71, 1.61} value, ok := s.Get(1) -// value will be 2.71 -// ok will be true +// value will be 2.71. +// ok will be true. ``` ### GetLength -Retrieves the element at a specified index in the slice, the length of the slice, and a boolean indicating success. +Retrieves the element at a specified index in the slice, a boolean indicating success and the length of the slice. ```Go s := &slice.Slice[int]{10, 20, 30, 40, 50} -value, length, ok := s.GetLength(2) -// value will be 30 -// length will be 5 -// ok will be true +value, ok, length := s.GetLength(2) +// value will be 30. +// ok will be true. +// length will be 5. ``` ### IsEmpty Checks if the slice is empty. ```Go s := &slice.Slice[int]{} -isEmpty := s.IsEmpty() // isEmpty will be true +isEmpty := s.IsEmpty() // isEmpty will be true. ``` ### IsPopulated Checks if the slice is not empty. ```Go s := &slice.Slice[int]{10, 20, 30} -isPopulated := s.IsPopulated() // isPopulated will be true +isPopulated := s.IsPopulated() // isPopulated will be true. ``` ### Length Returns the number of elements in the slice. ```Go s := &slice.Slice[int]{10, 20, 30, 40, 50} -length := s.Length() // length will be 5 +length := s.Length() // length will be 5. ``` ### Make Empties the slice and sets it to a specified length. ```Go s := &slice.Slice[int]{10, 20, 30} -s.Make(3) // s will be an empty Slice of length 3 +s.Make(3) // s will be an empty Slice of length 3. ``` ### MakeEach Empties the slice, sets it to a specified length, and populates it with provided values. ```Go s := &slice.Slice[int]{} -s.MakeEach(10, 20, 30) // s will be a Slice containing {10, 20, 30} +s.MakeEach(10, 20, 30) // s will be a Slice containing {10, 20, 30}. ``` ### MakeEachReverse Empties the slice, sets it to a specified length, and populates it with provided values in reverse order. ```Go s := &slice.Slice[int]{} -s.MakeEachReverse(10, 20, 30) // s will be a Slice containing {30, 20, 10} +s.MakeEachReverse(10, 20, 30) // s will be a Slice containing {30, 20, 10}. ``` ### Map -Executes a provided function for each element and sets the returned value to the current index. +Executes a provided function for each element and sets the returned value to a new slice at the current index. ```Go s := &slice.Slice[int]{10, 20, 30} s.Map(func(i int, value int) int { return value * 2 -}) // s will be a Slice containing {20, 40, 60} +}) // s will be a Slice containing {20, 40, 60}. ``` ### MapReverse -Executes a provided function for each element in reverse order and sets the returned value to the current index. +Executes a provided function for each element in reverse order and sets the returned value to a new slice at the current index. ```Go s := &slice.Slice[int]{10, 20, 30} s.MapReverse(func(i int, value int) int { return value * 2 -}) // s will be a Slice containing {60, 40, 20} +}) // s will be a Slice containing {60, 40, 20}. ``` ### Modify @@ -337,7 +365,17 @@ s := slice.Slice[int]{1, 2, 3, 4, 5} modifiedSlice := numbers.Modify(func(i int, value int) int { return value * 2 }) -// modifiedSlice: [2, 4, 6, 8, 10] +// modifiedSlice: [2, 4, 6, 8, 10]. +``` + +###ModifyReverseModifyReverse +Modify applies the provided function to each element in the slice in reverse order and modifies the elements in place. +```Go +s := slice.Slice[int]{1, 2, 3, 4, 5} +modifiedSlice := numbers.Modify(func(i int, value int) int { + return value * 2 +}) +// modifiedSlice: [2, 4, 6, 8, 10]. ``` ### Poll @@ -351,7 +389,7 @@ value := s.Poll() // value will be 10, and s will be [20, 30]. Removes the first element from the slice and returns the removed element and the length of the modified slice. ```Go s := &slice.Slice[int]{10, 20, 30} -value, length := s.Poll() // value will be 10, length will be 2, and s will be [20, 30] +value, length := s.Poll() // value will be 10, length will be 2, and s will be [20, 30]. ``` ### PollOK @@ -373,14 +411,14 @@ value := s.Pop() Removes the last element from the slice and returns the removed element and the length of the modified slice. ```Go s := &slice.Slice[int]{10, 20, 30} -value, length := s.PopLength() // value will be 30, length will be 2, and s will be [10, 20] +value, length := s.PopLength() // value will be 30, length will be 2, and s will be [10, 20]. ``` ### PopOK Removes and returns the last element from the slice and returns a boolean indicating success. ```Go s := &slice.Slice[int]{10, 20, 30} -value, ok := s.PopOK() // value will be 30, ok will be true, and s will be [10, 20] +value, ok := s.PopOK() // value will be 30, ok will be true, and s will be [10, 20]. ``` ### Precatenate @@ -388,7 +426,7 @@ Merges elements from another slice to the head of the receiver slice. ```Go s1 := &slice.Slice[int]{1, 2, 3} s2 := &slice.Slice[int]{4, 5} -s1.Precatenate(s2) // s1 will be [4, 5, 1, 2, 3] +s1.Precatenate(s2) // s1 will be [4, 5, 1, 2, 3]. ``` ### PrecatenateFunc @@ -406,30 +444,30 @@ Merges elements from another slice to the head of the receiver slice and returns ```Go s1 := &slice.Slice[int]{1, 2, 3} s2 := &slice.Slice[int]{4, 5} -length := s1.PrecatenateLength(s2) // length will be 5, and s1 will be [4, 5, 1, 2, 3] +length := s1.PrecatenateLength(s2) // length will be 5, and s1 will be [4, 5, 1, 2, 3]. ``` ### Prepend Adds one element to the head of the slice. ```Go s := &slice.Slice[int]{2, 3} -s.Prepend(1) // s will be [1, 2, 3] +s.Prepend(1) // s will be [1, 2, 3]. ``` ### PrependFunc Prepends elements to the head of the slice based on a provided predicate function. ```Go s := &slice.Slice[int]{1, 2, 3} -result := s.PrependFunc(func(i int, value int) bool { +result := s.PrependFunc([]int{4, 5, 6}, func(i int, value int) bool { return value%2 == 0 -}, 4, 5, 6) // 's' will be modified to [6, 4, 2, 1, 3], and 'result' will be a pointer to 's'. +}) // 's' will be modified to [6, 4, 2, 1, 3], and 'result' will be a pointer to 's'. ``` ### PrependLength Adds multiple elements to the head of the slice and returns the length of the modified slice. ```Go s := &slice.Slice[int]{2, 3} -length := s.PrependLength(1, 0) // length will be 4, and s will be [1, 0, 2, 3] +length := s.PrependLength(1, 0) // length will be 4, and s will be [1, 0, 2, 3]. ``` ### Reduce @@ -439,7 +477,7 @@ s := slice.Slice[int]({1, 2, 3, 4, 5}) sum := numbers.Reduce(func(i int, currentValue int, resultValue int) int { return resultValue + currentValue }) -// sum: 15 (1 + 2 + 3 + 4 + 5) +// sum: 15 (1 + 2 + 3 + 4 + 5). ``` ### ReduceReverse @@ -449,99 +487,122 @@ s := slice.Slice[int]{1, 2, 3, 4, 5} sum := numbers.ReduceReverse(func(i int, currentValue, resultValue int) int { return currentValue + resultValue }) -// sum: 15 (sum of all elements in the slice) +// sum: 15 (sum of all elements in the slice). ``` ### Replace Replaces the element at the index with the provided value. ```Go s := &slice.Slice[int]{1, 2, 3} -ok := s.Replace(1, 4) // ok will be true, and s will be [1, 4, 3] +ok := s.Replace(1, 4) // ok will be true, and s will be [1, 4, 3]. ``` ### Reverse Reverses the order of the slice. ```Go s := &slice.Slice[int]{1, 2, 3} -s.Reverse() // s will be [3, 2, 1] +s.Reverse() // s will be [3, 2, 1]. ``` ### Set Creates a new slice containing opnly unique values. ```Go s := &slice.Slice[int]{1, 2, 2, 3, 3, 3} -s.Set() // s will be [1, 2, 3] +s.Set() // s will be [1, 2, 3]. ``` ### Shuffle Randomly shuffles elements in the slice. ```Go s := &slice.Slice[int]{1, 2, 3, 4, 5} -s.Shuffle() // s will be a random permutation of [1, 2, 3, 4, 5] +s.Shuffle() // s will be a random permutation of [1, 2, 3, 4, 5]. ``` ### Slice Creates a subset of the values based on the beginning and end index. ```Go s := &slice.Slice[int]{1, 2, 3, 4, 5} -newSlice := s.Slice(1, 3) // newSlice will be [2, 3, 4] +newSlice := s.Slice(1, 3) // newSlice will be [2, 3, 4]. +``` + +### SortFunc +Sorts elements in the slice that satisfy a provided predicate function. +```Go +s := &slice.Slice[int]{2, 1, 5, 3} +s.SortFunc(func(i int, j int, a int, b int) bool { + return a < b +}) // s will be [1, 2, 3, 5]. ``` ### Splice Modifies the slice to include only the values based on the beginning and end index. ```Go s := &slice.Slice[int]{1, 2, 3, 4, 5} -slice.Split(1, 3) // s will be [2, 3, 4] +slice.Split(1, 3) // s will be [2, 3, 4]. ``` -### SortFunc -Sorts elements in the slice that satisfy a provided predicate function. +### Split +Divides the slice into two slices at the specified index and returns the two new slices. ```Go -s := &slice.Slice[int]{2, 1, 5, 3} -s.SortFunc(func(i int, j int, a int, b int) bool { - return a < b -}) // s will be [1, 2, 3, 5] +s := &slice.Slice[int]{1, 2, 3, 4} +a, b := s.Split(2) // a will be [1, 2], be will be [3, 4]. +``` + +### SplitFunc +Divides the slice into two slices based on the provided function and returns the two new slices. +```Go +s := &slice.Slice[int]{1, 2, 3, 4} +a, b := s.SplitFunc(func(i int, value int) bool { + return value%2 == 0 +}) // a will be [1, 3], b will be [2, 4]. +``` + +### SplitOK +Divides the slice into two slices at the specified index and returns the two new slices, or false if the index is invalid. +```Go +s := &slice.Slice[int]{1, 2, 3, 4} +a, b, ok := s.Split(2) // a will be [1, 2], be will be [3, 4], ok will be true. ``` ### Swap Swaps values at indexes i and j. ```Go s := &slice.Slice[int]{1, 2, 3} -s.Swap(0, 2) // s will be [3, 2, 1] +s.Swap(0, 2) // s will be [3, 2, 1]. ``` ## Examples ### Struct ```Go -// Define a custom struct +// Define a custom struct. type Person struct { Name string Age int Email string } -// Create a slice of Person structs +// Create a slice of Person structs. people := &slice.Slice[Person]{ {Name: "Alice", Age: 30, Email: "alice@example.com"}, {Name: "Bob", Age: 25, Email: "bob@example.com"}, } -// Append a new person to the slice +// Append a new person to the slice. newPerson := Person{Name: "Charlie", Age: 35, Email: "charlie@example.com"} people.Append(newPerson) -// Find the index of a person with a specific email address +// Find the index of a person with a specific email address. index := people.FindIndex(func(p Person) bool { return p.Email == "bob@example.com" }) -// Slice the slice to include only people aged 30 or older +// Slice the slice to include only people aged 30 or older. people.Slice(1, people.Length()) -// Reverse the order of people in the slice +// Reverse the order of people in the slice. people.Reverse() -// Iterate over the slice and print each person's details +// Iterate over the slice and print each person's details. people.Each(func(index int, person Person) { fmt.Printf("Index %d: Name: %s, Age: %d, Email: %s\n", index, person.Name, person.Age, person.Email) }) @@ -552,7 +613,7 @@ people.Each(func(index int, person Person) { s := (&slice.Slice[int64]{1, 2, 3}).Append(4, 5, 6).Filter(func(_ int, value int64) bool { return value%2 == 0 }) -fmt.Println(s) // 2, 4, 6 +fmt.Println(s) // 2, 4, 6. ``` ## Docker diff --git a/benchmark_test.go b/benchmark_test.go index 8cf4c60..e8fcc7f 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -1,111 +1,586 @@ package slice_test import ( + "math/rand" "testing" "github.com/lindsaygelle/slice" ) func BenchmarkAppend(b *testing.B) { - s := &slice.Slice[int]{1, 2, 3, 4, 5} + slice := &slice.Slice[int]{} + values := make([]int, b.N) + for i := 0; i < b.N; i++ { + values[i] = i + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + slice.Append(values[i]) + } +} - // Run the benchmark +func BenchmarkAppendFunc(b *testing.B) { + slice := &slice.Slice[int]{} + values := make([]int, b.N) + for i := 0; i < b.N; i++ { + values[i] = i + } + fn := func(i int, value int) bool { + return true + } b.ResetTimer() + for i := 0; i < b.N; i++ { - s.Append(6) + slice.AppendFunc(values, fn) } } func BenchmarkAppendLength(b *testing.B) { - s := &slice.Slice[int]{1, 2, 3, 4, 5} + slice := &slice.Slice[int]{} + values := make([]int, b.N) + for i := 0; i < b.N; i++ { + values[i] = i + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = slice.AppendLength(values...) + } +} + +func BenchmarkBounds(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Bounds(i) + } +} + +func BenchmarkClone(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } b.ResetTimer() + for i := 0; i < b.N; i++ { - s.AppendLength(6) + _ = slice.Clone() } } func BenchmarkConcatenate(b *testing.B) { - s1 := &slice.Slice[int]{} - s2 := &slice.Slice[int]{} + slice1 := &slice.Slice[int]{} + slice2 := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice1.Append(i) + slice2.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice1.Concatenate(slice2) + } +} + +func BenchmarkConcatenateFunc(b *testing.B) { + slice1 := &slice.Slice[int]{} + slice2 := &slice.Slice[int]{} for i := 0; i < b.N; i++ { - s1.Append(i) - s2.Append(i) + slice1.Append(i) + slice2.Append(i) + } + fn := func(i int, value int) bool { + return true + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice1.ConcatenateFunc(slice2, fn) + } +} + +func BenchmarkConcatenateLength(b *testing.B) { + slice1 := &slice.Slice[int]{} + slice2 := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice1.Append(i) + slice2.Append(i) } b.ResetTimer() + for i := 0; i < b.N; i++ { - s1.Concatenate(s2) + _ = slice1.ConcatenateLength(slice2) + } +} + +func BenchmarkContains(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + value := rand.Intn(b.N) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Contains(value) + } +} + +func BenchmarkContainsMany(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + values := make([]int, b.N) + for i := 0; i < b.N; i++ { + values[i] = i + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.ContainsMany(values...) + } +} + +func BenchmarkDeduplicate(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(rand.Intn(b.N)) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Deduplicate() } } func BenchmarkDelete(b *testing.B) { - s := &slice.Slice[int]{} + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Delete(i % slice.Length()) + } +} + +func BenchmarkDeleteFunc(b *testing.B) { + slice := &slice.Slice[int]{} for i := 0; i < b.N; i++ { - s.Append(i) + slice.Append(i) + } + fn := func(i int, value int) bool { + return true } b.ResetTimer() + for i := 0; i < b.N; i++ { - s.Delete(i % s.Length()) + _ = slice.DeleteFunc(fn) + } +} + +func BenchmarkDeleteLength(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.DeleteLength(i % slice.Length()) + } +} + +func BenchmarkDeleteOK(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.DeleteOK(i % slice.Length()) + } +} + +func BenchmarkDeleteUnsafe(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.DeleteUnsafe(i % slice.Length()) } } func BenchmarkEach(b *testing.B) { - s := &slice.Slice[int]{} + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + fn := func(i int, value int) {} + b.ResetTimer() + for i := 0; i < b.N; i++ { - s.Append(i) + _ = slice.Each(fn) + } +} + +func BenchmarkEachBreak(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + fn := func(i int, value int) bool { + return true } - fn := func(_ int, _ int) {} b.ResetTimer() + for i := 0; i < b.N; i++ { - s.Each(fn) + _ = slice.EachBreak(fn) + } +} + +func BenchmarkEachOK(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + fn := func(i int, value int) bool { + return true + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.EachOK(fn) + } +} + +func BenchmarkEachReverse(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + fn := func(i int, value int) {} + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.EachReverse(fn) + } +} + +func BenchmarkEachReverseBreak(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + fn := func(i int, value int) bool { + return true + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.EachReverseBreak(fn) + } +} + +func BenchmarkEachReverseOK(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + fn := func(i int, value int) bool { + return true + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.EachReverseOK(fn) + } +} + +func BenchmarkEqual(b *testing.B) { + slice1 := &slice.Slice[int]{} + slice2 := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice1.Append(i) + slice2.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice1.Equal(slice2) + } +} + +func BenchmarkEqualFunc(b *testing.B) { + slice1 := &slice.Slice[int]{} + slice2 := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice1.Append(i) + slice2.Append(i) + } + fn := func(i int, a, b int) bool { + return a == b + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice1.EqualFunc(slice2, fn) + } +} + +func BenchmarkEqualLength(b *testing.B) { + slice1 := &slice.Slice[int]{} + slice2 := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice1.Append(i) + slice2.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice1.EqualLength(slice2) + } +} + +func BenchmarkFetch(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Fetch(i) + } +} + +func BenchmarkFetchLength(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, _ = slice.FetchLength(i) + } +} + +func BenchmarkFilter(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + fn := func(i int, value int) bool { + return value%2 == 0 + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Filter(fn) } } func BenchmarkFindIndex(b *testing.B) { - s := &slice.Slice[int]{} + slice := &slice.Slice[int]{} for i := 0; i < b.N; i++ { - s.Append(i) + slice.Append(i) + } + fn := func(value int) bool { + return value == b.N/2 } b.ResetTimer() + for i := 0; i < b.N; i++ { - _, _ = s.FindIndex(func(value int) bool { - return value == i - }) + _, _ = slice.FindIndex(fn) + } +} + +func BenchmarkGet(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, _ = slice.Get(i) + } +} + +func BenchmarkGetLength(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, _, _ = slice.GetLength(i) + } +} + +func BenchmarkIsEmpty(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.IsEmpty() + } +} + +func BenchmarkIsPopulated(b *testing.B) { + slice := &slice.Slice[int]{} + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.IsPopulated() + } +} + +func BenchmarkLength(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Length() } } func BenchmarkMap(b *testing.B) { - s := &slice.Slice[int]{} + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + fn := func(i int, value int) int { + return value * value + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Map(fn) + } +} + +func BenchmarkPop(b *testing.B) { + slice := &slice.Slice[int]{} for i := 0; i < b.N; i++ { - s.Append(i) + slice.Append(i) } - fn := func(_ int, value int) int { - return value * 2 + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Pop() + } +} + +func BenchmarkPopLength(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) } b.ResetTimer() + for i := 0; i < b.N; i++ { - s.Map(fn) + _, _ = slice.PopLength() + } +} + +func BenchmarkReduce(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + fn := func(i, acc, value int) int { + return acc + value + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Reduce(fn) } } func BenchmarkReverse(b *testing.B) { - s := &slice.Slice[int]{} + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Reverse() + } +} + +func BenchmarkShuffle(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _ = slice.Shuffle() + } +} + +func BenchmarkSlice(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(i) + } + start := b.N / 4 + end := 3 * b.N / 4 + b.ResetTimer() + for i := 0; i < b.N; i++ { - s.Append(i) + _ = slice.Slice(start, end) + } +} + +func BenchmarkSortFunc(b *testing.B) { + slice := &slice.Slice[int]{} + for i := 0; i < b.N; i++ { + slice.Append(rand.Intn(b.N)) + } + fn := func(i, j, a, b int) bool { + return a < b } b.ResetTimer() + for i := 0; i < b.N; i++ { - s.Reverse() + _ = slice.SortFunc(fn) } } -func BenchmarkSet(b *testing.B) { - s := &slice.Slice[int]{} +func BenchmarkSwap(b *testing.B) { + slice := &slice.Slice[int]{} for i := 0; i < b.N; i++ { - s.Append(i) + slice.Append(i) } + index1 := b.N / 4 + index2 := 3 * b.N / 4 b.ResetTimer() + for i := 0; i < b.N; i++ { - s.Set() + slice.Swap(index1, index2) } } diff --git a/doc.go b/doc.go index 86486ce..38c9dec 100644 --- a/doc.go +++ b/doc.go @@ -1,3 +1,3 @@ // Package slice is a Go package that offers a generic slice with extended functionality. -// It abstracts common list operations, such as appending, deleting, concatenating, mapping, and more, making it easier to work with slices in Go. +// It abstracts common list operations, such as appending, deleting, concatenating, filtering, mapping, and more, making it easier to work with slices in Go. package slice diff --git a/example_test.go b/example_test.go index 552e47f..a64f9f1 100644 --- a/example_test.go +++ b/example_test.go @@ -2,76 +2,36 @@ package slice_test import ( "fmt" + "net/http" "github.com/lindsaygelle/slice" ) func ExampleNew() { - // Create a new Slice - s := slice.New(1, 2, 3, 4, 5) + // Creating a new integer slice + intSlice := slice.New[int](1, 2, 3, 4, 5) - // Append values to the Slice - s.Append(6, 7, 8) - fmt.Println("Appended:", s) + // Print the created slice + fmt.Println("Integer Slice:", intSlice) - // Append values based on a custom condition - s.AppendFunc(func(i int, value int) bool { - return value%2 == 0 - }, 10, 11, 12) - fmt.Println("Appended based on condition:", s) + // Creating a new string slice + stringSlice := slice.New[string]("apple", "orange", "banana", "grape") - // Get the length of the Slice - fmt.Println("Length of Slice:", s.Length()) + // Print the created slice + fmt.Println("String Slice:", stringSlice) - // Check if the Slice contains a specific value - fmt.Println("Contains 3:", s.Contains(3)) // Should print true - fmt.Println("Contains 9:", s.Contains(9)) // Should print false + // Creating a new http.Request slice + httpRequestSlice := slice.New[http.Request](http.Request{}) - // Create a new Slice of booleans indicating if values are present in the original Slice - contains := s.ContainsMany(2, 5, 8, 10) - fmt.Println("Contains:", contains) + // Print the created slice + fmt.Println(httpRequestSlice) - // Delete an element at a specific index - s.Delete(2) - fmt.Println("Deleted at index 2:", s) + // Define a custom struct type + type Animal struct{ Name string } - // Iterate over the Slice and apply a function to each element - s.Each(func(i int, value int) { - fmt.Printf("Index %d: %d\n", i, value) - }) - - // Find the index of an element that satisfies a condition - index, found := s.FindIndex(func(value int) bool { - return value == 4 - }) - if found { - fmt.Println("Index of 4:", index) // Should print 3 - } else { - fmt.Println("4 not found") - } - - // Get an element at a specific index - value, ok := s.Get(1) - if ok { - fmt.Println("Value at index 1:", value) // Should print 2 - } else { - fmt.Println("Index 1 not found") - } - - // Make a new Slice with specific values - s = s.MakeEach(5, 4, 3, 2, 1) - fmt.Println("New Slice:", s) - - // Reverse the Slice - s.Reverse() - fmt.Println("Reversed Slice:", s) - - // Shuffle the Slice - s.Shuffle() - fmt.Println("Shuffled Slice:", s) - - // Slice the Slice from index 2 to 5 (exclusive) - s.Slice(2, 5) - fmt.Println("Sliced Slice:", s) + // Creating a custom slice + customSlice := slice.New[Animal](Animal{"Cat"}, Animal{"Dog"}) + // Print the created slice + fmt.Println(customSlice) } diff --git a/slice.go b/slice.go index 94a2219..38417f3 100644 --- a/slice.go +++ b/slice.go @@ -7,116 +7,42 @@ import ( "sort" ) -// Slice is a generic list-like struct that allows for the manipulation and traversal of elements by numeric index. -// It is parameterized with the type T, allowing it to work with slices of any data type. -// -// Example usage:. -// -// // Create a Slice of integers. -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// -// // Append values to the Slice. -// s.Append(6, 7, 8). -// -// // Check if a value exists in the Slice. -// contains := s.Contains(3) // contains is true. -// -// // Find the index of the first element that satisfies a condition. -// index, found := s.FindIndex(func(value int) bool {. -// return value > 4. -// }). -// -// // Delete an element by index. -// s.Delete(2) // Removes the element at index 2. -// -// // Iterate over the elements and perform an operation on each. -// s.Each(func(i int, value int) {. -// fmt.Printf("Element %d: %d\n", i, value). -// }). -// -// This type provides a set of methods for common Slice operations and is designed to be generic for flexibility. +// Slice represents a generic slice of any data type. type Slice[T any] []T -// Append appends the specified values to the end of the Slice and returns a pointer to the modified Slice. -// It extends the Slice by adding the provided values to the end, updating the Slice in place. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// s.Append(4, 5) // s is now [1, 2, 3, 4, 5]. +// Append appends the given values to the slice and returns the modified slice. func (slice *Slice[T]) Append(values ...T) *Slice[T] { *slice = append(*slice, values...) return slice } -// AppendFunc appends selected elements to the end of the Slice based on a provided condition. -// It iterates over the specified values, invoking the provided function for each element. -// If the function returns true for an element, that element is added to the end of the Slice. -// -// Example:. -// -// s := &slice.Slice[int]{}. -// s.AppendFunc(func(i int, value int) bool {. -// return value%2 == 0 // Append even numbers to the Slice. -// }, 1, 2, 3, 4, 5). -// -// After this operation, s will contain [2, 4]. -// -// This method modifies the original Slice and returns a pointer to the modified Slice. -func (slice *Slice[T]) AppendFunc(fn func(i int, value T) bool, values ...T) *Slice[T] { - var s Slice[T] +// AppendFunc appends values to the slice based on the provided function and returns the modified slice. +func (slice *Slice[T]) AppendFunc(values []T, fn func(i int, value T) bool) *Slice[T] { for i, value := range values { - if ok := fn(i, value); ok { - s = append(s, value) + if fn(i, value) { + slice.Append(value) } } - *slice = append(*slice, s...) return slice } -// AppendLength appends the specified values to the end of the Slice and returns the length of the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// length := s.AppendLength(4, 5) // s is now [1, 2, 3, 4, 5], length is 5. +// AppendLength appends values to the slice and returns the length of the modified slice. func (slice *Slice[T]) AppendLength(values ...T) int { return slice.Append(values...).Length() } -// Bounds checks if the given integer index is within the valid range of indices for the Slice. -// It returns true if the index is greater than or equal to 0 and less than the length of the slice, indicating that the index is within bounds. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// inBounds := s.Bounds(1) // inBounds is true. -// outOfBounds := s.Bounds(5) // outOfBounds is false. +// Bounds checks if the given index is within the bounds of the slice. func (slice *Slice[T]) Bounds(i int) bool { return i >= 0 && i < slice.Length() } -// Clone creates and returns a new slice that contains the same elements as the original slice. -// The original slice remains unchanged. -// -// Example:. -// -// numbers := slice.Slice[int]{1, 2, 3, 4, 5}. -// clonedSlice := numbers.Clone(). -// // clonedSlice: [1, 2, 3, 4, 5]. +// Clone creates a new slice that is a copy of the original slice. func (slice *Slice[T]) Clone() *Slice[T] { s := *slice return &s } -// Concatenate merges the elements from the argument Slice to the tail of the receiver Slice and returns the modified Slice. -// If the provided Slice (s) is not nil, it appends its elements to the end of the receiver slice, updating the Slice in place. -// -// Example:. -// -// s1 := &slice.Slice[int]{1, 2, 3}. -// s2 := &slice.Slice[int]{4, 5}. -// s1.Concatenate(s2) // s1 is now [1, 2, 3, 4, 5]. +// Concatenate concatenates the given slice with the original slice and returns the modified slice. func (slice *Slice[T]) Concatenate(s *Slice[T]) *Slice[T] { if s != nil { slice.Append((*s)...) @@ -124,57 +50,30 @@ func (slice *Slice[T]) Concatenate(s *Slice[T]) *Slice[T] { return slice } -// ConcatenateFunc appends elements from the provided Slice (s) to the end of the receiver slice, based on the result of a filtering function. -// -// Example:. -// -// s1 := &slice.Slice[int]{1, 2, 3}. -// s2 := &slice.Slice[int]{4, 5, 6}. -// s1.ConcatenateFunc(s2, func(i int, value int) bool {. -// return value%2 == 0. -// }) // s1 is now [1, 2, 3, 4, 6]. +// ConcatenateFunc concatenates values based on the provided function and returns the modified slice. func (slice *Slice[T]) ConcatenateFunc(s *Slice[T], fn func(i int, value T) bool) *Slice[T] { if s != nil { - slice.AppendFunc(fn, *s...) + slice.AppendFunc(*s, fn) } return slice } -// ConcatenateLength merges the elements from the argument Slice to the tail of the receiver Slice and returns the length of the modified Slice. -// -// Example:. -// -// s1 := &slice.Slice[int]{1, 2, 3}. -// s2 := &slice.Slice[int]{4, 5}. -// length := s1.ConcatenateLength(s2) // s1 is now [1, 2, 3, 4, 5], length is 5. +// ConcatenateLength concatenates the given slice with the original slice and returns the length of the modified slice. func (slice *Slice[T]) ConcatenateLength(s *Slice[T]) int { return slice.Concatenate(s).Length() } -// Contains iterates over the elements of the Slice and compares each element with the provided value. -// If a matching element is found, it returns true; otherwise, it returns false. -// -// Example:. -// -// s := &slice.Slice[string]{"apple", "banana", "cherry"}. -// containsBanana := s.Contains("banana") // containsBanana is true. +// Contains checks if the slice contains the given value. func (slice *Slice[T]) Contains(value T) bool { - for _, v := range *slice { - if reflect.DeepEqual(v, value) { - return true - } - } - return false + var ok bool + slice.EachBreak(func(i int, v T) bool { + ok = reflect.DeepEqual(v, value) + return !ok + }) + return ok } -// ContainsMany checks if multiple values exist in the Slice and returns a boolean Slice indicating their presence. -// It takes a variadic number of values and checks each of them against the elements in the Slice. -// The returned boolean Slice will have 'true' at the corresponding index if the value is found, 'false' otherwise. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// result := s.ContainsMany(2, 4, 6) // result will be [true, true, false]. +// ContainsMany checks if the slice contains any of the given values and returns a boolean slice indicating the results. func (slice *Slice[T]) ContainsMany(values ...T) *Slice[bool] { s := &Slice[bool]{} for _, value := range values { @@ -183,14 +82,22 @@ func (slice *Slice[T]) ContainsMany(values ...T) *Slice[bool] { return s } -// Delete removes the element at the specified index from the slice, if the index is within bounds. -// It modifies the Slice in place by removing the element at the given index and returns a pointer to the modified Slice. -// If the index is out of bounds, it does not modify the Slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// s.Delete(2) // s is now [1, 2, 4, 5]. +// Deduplicate removes duplicate values from the slice and returns the modified slice. +func (slice *Slice[T]) Deduplicate() *Slice[T] { + uniqueValues := make(map[string]bool) + var uniqueSlice Slice[T] + + slice.Each(func(_ int, value T) { + if !uniqueValues[fmt.Sprintf("%v", value)] { + uniqueValues[fmt.Sprintf("%v", value)] = true + uniqueSlice.Append(value) + } + }) + *slice = uniqueSlice + return slice +} + +// Delete removes the element at the specified index from the slice and returns the modified slice. func (slice *Slice[T]) Delete(i int) *Slice[T] { if slice.Bounds(i) { slice.DeleteUnsafe(i) @@ -198,21 +105,11 @@ func (slice *Slice[T]) Delete(i int) *Slice[T] { return slice } -// DeleteFunc removes elements from the Slice based on the provided predicate function. -// It iterates over each element of the Slice and applies the given function to each element. -// If the function returns true for an element, that element is removed from the slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// even := func(i int, value int) bool { return value%2 == 0 }. -// s.DeleteFunc(even). -// // 's' will contain [1, 3, 5] after removing even elements. +// DeleteFunc removes elements from the slice based on the provided function and returns the modified slice. func (slice *Slice[T]) DeleteFunc(fn func(i int, value T) bool) *Slice[T] { length := slice.Length() for i := 0; i < length; i++ { if fn(i, slice.Fetch(i)) { - // Delete the element at index i. slice.DeleteUnsafe(i) i-- // Adjust the index after deletion. length-- // Update the length. @@ -221,26 +118,12 @@ func (slice *Slice[T]) DeleteFunc(fn func(i int, value T) bool) *Slice[T] { return slice } -// DeleteLength removes the element at the specified index from the slice, if the index is within bounds, and returns the new length of the modified Slice. -// It modifies the Slice in place by removing the element at the given index and returns the new length of the Slice. -// If the index is out of bounds, it does not modify the Slice and returns the current length. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// newLength := s.DeleteLength(2) // s is now [1, 2, 4, 5], newLength is 4. +// DeleteLength removes the element at the specified index from the slice and returns the length of the modified slice. func (slice *Slice[T]) DeleteLength(i int) int { return slice.Delete(i).Length() } -// DeleteOK removes the element at the specified index from the Slice if the index is within bounds and returns the result of the transaction. -// It modifies the Slice in place by removing the element at the given index and returns true if the deletion was successful. -// If the index is out of bounds, it does not modify the Slice and returns false. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// deleted := s.DeleteOK(2) // s is now [1, 2, 4, 5], deleted is true. +// DeleteOK removes the element at the specified index from the slice if it exists and returns true, or false otherwise. func (slice *Slice[T]) DeleteOK(i int) bool { if slice.Bounds(i) { slice.Delete(i) @@ -249,29 +132,13 @@ func (slice *Slice[T]) DeleteOK(i int) bool { return false } -// DeleteUnsafe deletes the element from the specified index without bounds checking. -// It removes the element at the given index without checking whether the index is within the bounds of the slice. -// Be cautious when using this method to avoid index out-of-range errors. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// s.DeleteUnsafe(2). -// // The Slice becomes [1, 2, 4, 5] with the element at index 2 (value 3) removed. +// DeleteUnsafe removes the element at the specified index from the slice without performing bounds checks and returns the modified slice. func (slice *Slice[T]) DeleteUnsafe(i int) *Slice[T] { *slice = append((*slice)[:i], (*slice)[i+1:]...) return slice } -// Each executes a provided function once for each element in the Slice and returns the Slice. -// It iterates over each element of the slice, invoking the provided function for each element, and returns a pointer to the modified Slice. -// -// Example:. -// -// s := &slice.Slice[string]{"apple", "banana", "cherry"}. -// s.Each(func(i int, value string) {. -// fmt.Printf("Element %d: %s\n", i, value). -// }). +// Each applies the given function to each element of the slice and returns the modified slice. func (slice *Slice[T]) Each(fn func(i int, value T)) *Slice[T] { slice.EachBreak(func(i int, value T) bool { fn(i, value) @@ -280,17 +147,7 @@ func (slice *Slice[T]) Each(fn func(i int, value T)) *Slice[T] { return slice } -// EachBreak executes a provided function once for each element in the Slice with an optional break when the function returns false. -// It iterates over each element of the slice, invoking the provided function for each element. If the function returns false, the iteration stops. -// It returns a pointer to the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// s.EachBreak(func(i int, value int) bool {. -// fmt.Printf("Element %d: %d\n", i, value). -// return i < 3 // Stop iteration when i is less than 3. -// }). +// EachBreak applies the given function to each element of the slice until the function returns false and returns the modified slice. func (slice *Slice[T]) EachBreak(fn func(i int, value T) bool) *Slice[T] { for i, v := range *slice { if !fn(i, v) { @@ -300,15 +157,17 @@ func (slice *Slice[T]) EachBreak(fn func(i int, value T) bool) *Slice[T] { return slice } -// EachReverse executes a provided function once for each element in the reverse order they are stored in the Slice. -// It iterates over each element of the Slice in reverse order, invoking the provided function for each element, and returns a pointer to the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// s.EachReverse(func(i int, value int) {. -// fmt.Printf("Element %d: %d\n", i, value). -// }). +// EachOK applies the given function to each element of the slice and returns true if the function returned true for all elements, or false otherwise. +func (slice *Slice[T]) EachOK(fn func(i int, value T) bool) bool { + var ok bool + slice.EachBreak(func(i int, value T) bool { + ok = fn(i, value) + return ok + }) + return ok +} + +// EachReverse applies the given function to each element of the slice in reverse order and returns the modified slice. func (slice *Slice[T]) EachReverse(fn func(i int, value T)) *Slice[T] { slice.EachReverseBreak(func(i int, value T) bool { fn(i, value) @@ -317,20 +176,9 @@ func (slice *Slice[T]) EachReverse(fn func(i int, value T)) *Slice[T] { return slice } -// EachReverseBreak executes a provided function once for each element in the reverse order they are stored in the Slice with an optional break when the function returns false. -// It iterates over each element of the Slice in reverse order, invoking the provided function for each element. If the function returns false, the iteration stops. -// It returns a pointer to the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// s.EachReverseBreak(func(i int, value int) bool {. -// fmt.Printf("Element %d: %d\n", i, value). -// return i > 2 // Stop iteration when i is greater than 2. -// }). +// EachReverseBreak applies the given function to each element of the slice in reverse order until the function returns false and returns the modified slice. func (slice *Slice[T]) EachReverseBreak(fn func(i int, value T) bool) *Slice[T] { for i := slice.Length() - 1; i >= 0; i-- { - // If the function returns false, break out of the loop. if !fn(i, (*slice)[i]) { break } @@ -338,79 +186,53 @@ func (slice *Slice[T]) EachReverseBreak(fn func(i int, value T) bool) *Slice[T] return slice } -// Equal checks if the current Slice is equal to another Slice by comparing their elements. -// It returns true if the two slices have the same length and all corresponding elements are deeply equal. -// -// Example:. -// -// s1 := slice.Slice[int]{1, 2, 3}. -// s2 := slice.Slice[int]{1, 2, 3}. -// equal := s1.Equal(s2) // true. +// EachReverseOK applies the given function to each element of the slice in reverse order and returns true if the function returned true for all elements, or false otherwise. +func (slice *Slice[T]) EachReverseOK(fn func(i int, value T) bool) bool { + var ok bool + slice.EachReverseBreak(func(i int, value T) bool { + ok = fn(i, value) + return ok + }) + return ok +} + +// Equal checks if the slice is equal to another slice based on the element values. func (slice *Slice[T]) Equal(s *Slice[T]) bool { return slice.EqualFunc(s, func(i int, value1, value2 T) bool { return reflect.DeepEqual(value1, value2) }) } -// EqualFunc checks if the current Slice is equal to another Slice by applying a custom comparison function to their elements. -// It returns true if the two slices have the same length and the custom comparison function returns true for all corresponding elements. -// -// Example:. -// -// s1 := slice.Slice[int]{1, 2, 3}. -// s2 := slice.Slice[int]{2, 4, 6}. -// customEqual := func(i int, value1, value2 int) bool {. -// return value1*2 == value2. -// }. -// equal := s1.EqualFunc(s2, customEqual) // true. -func (slice *Slice[T]) EqualFunc(s *Slice[T], fn func(i int, value1, value2 T) bool) bool { - var ok bool - if slice.Length() != s.Length() { +// EqualFunc checks if the slice is equal to another slice based on the element values and a provided comparison function. +func (slice *Slice[T]) EqualFunc(s *Slice[T], fn func(i int, a T, b T) bool) bool { + if !slice.EqualLength(s) { return false } + var ok bool slice.EachBreak(func(i int, value T) bool { - ok = fn(i, value, s.Fetch(i)) + ok = fn(i, slice.Fetch(i), s.Fetch(i)) return ok }) return ok } -// Fetch retrieves the element held at the specified index in the Slice. -// -// Example:. -// -// s := &slice.Slice[string]{"apple", "banana", "cherry"}. -// fruit := s.Fetch(1). -// // fruit will be "banana". +// EqualLength checks if the length of the slice is equal to the length of another slice. +func (slice *Slice[T]) EqualLength(s *Slice[T]) bool { + return slice.Length() == s.Length() +} + +// Fetch returns the element at the specified index and a boolean indicating whether the index is valid. func (slice *Slice[T]) Fetch(i int) T { - v, _ := slice.Get(i) - return v -} - -// FetchLength retrieves the element held at the specified index in the Slice and the length of the Slice. -// It returns the element at the specified index and the length of the Slice. -// -// Example:. -// -// s := &slice.Slice[int]{10, 20, 30, 40, 50}. -// value, length := s.FetchLength(2). -// // value will be 30. -// // length will be 5. + value, _ := slice.Get(i) + return value +} + +// FetchLength returns the element at the specified index, a boolean indicating whether the index is valid, and the length of the slice. func (slice *Slice[T]) FetchLength(i int) (T, int) { return slice.Fetch(i), slice.Length() } -// Filter creates a new Slice containing only the elements that satisfy the given predicate function. -// It iterates over the elements of the Slice and applies the predicate function to each element. -// Elements for which the predicate returns true are included in the new Slice, and others are excluded. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// filtered := s.Filter(func(x int) bool {. -// return x%2 == 0 // Keep only even numbers. -// }). -// // filtered will be &Slice[int]{2, 4}. +// Filter returns a new slice containing elements that satisfy the provided function. func (slice *Slice[T]) Filter(fn func(i int, value T) bool) *Slice[T] { s := &Slice[T]{} slice.Each(func(i int, value T) { @@ -421,135 +243,61 @@ func (slice *Slice[T]) Filter(fn func(i int, value T) bool) *Slice[T] { return s } -// FindIndex finds the index of the first element that satisfies the given predicate function. -// It returns the index of the first matching element and true if found; otherwise, it returns -1 and false. -// -// Example:. -// -// s := &slice.Slice[string]{"apple", "banana", "cherry"}. -// index, found := s.FindIndex(func(fruit string) bool {. -// return fruit == "banana". -// }). -// // index will be 1. -// // found will be true. +// FindIndex finds the index of the first element that satisfies the provided function and returns the index and true, +// or -1 and false if no such element is found. func (slice *Slice[T]) FindIndex(fn func(value T) bool) (int, bool) { - var index int - var ok bool - slice.EachBreak(func(i int, value T) bool { - index = i - ok = fn(value) - if !ok { - index = -1 + for i, value := range *slice { + if fn(value) { + return i, true } - return !ok - }) - return index, ok -} - -// Get retrieves the element held at the specified index in the Slice and a boolean indicating if it was successfully retrieved. -// It returns the element at the specified index and a boolean indicating whether the element was successfully retrieved. -// -// Example:. -// -// s := &slice.Slice[float64]{3.14, 2.71, 1.61}. -// value, ok := s.Get(1). -// // value will be 2.71. -// // ok will be true. + } + return -1, false +} + +// Get returns the element at the specified index and a boolean indicating whether the index is valid. func (slice *Slice[T]) Get(i int) (T, bool) { - var ( - ok = slice.Bounds(i) - v T - ) - if ok { - v = (*slice)[i] + var value T + if !slice.Bounds(i) { + return value, false } - return v, ok -} - -// GetLength retrieves the element held at the specified index in the slice, the length of the slice, and a boolean indicating if it was successfully retrieved. -// It returns the element at the specified index, the length of the slice, and a boolean indicating whether the element was successfully retrieved. -// -// Example:. -// -// s := &slice.Slice[int]{10, 20, 30, 40, 50}. -// value, length, ok := s.GetLength(2). -// // value will be 30. -// // length will be 5. -// // ok will be true. -func (slice *Slice[T]) GetLength(i int) (T, int, bool) { - v, ok := slice.Get(i) - l := slice.Length() - return v, l, ok -} - -// IsEmpty returns whether the Slice is empty. -// It returns true if the Slice is empty (length is zero), otherwise false. -// -// Example:. -// -// s := &slice.Slice[int]{}. -// isEmpty := s.IsEmpty() // isEmpty will be true. + return (*slice)[i], true +} + +// GetLength returns the element at the specified index, a boolean indicating whether the index is valid, and the length of the slice. +func (slice *Slice[T]) GetLength(i int) (T, bool, int) { + value, ok := slice.Get(i) + return value, ok, slice.Length() +} + +// IsEmpty returns true if the slice is empty, or false otherwise. func (slice *Slice[T]) IsEmpty() bool { return slice.Length() == 0 } -// IsPopulated returns whether the Slice is populated. -// It returns true if the Slice is not empty (length is greater than zero), otherwise false. -// -// Example:. -// -// s := &slice.Slice[int]{10, 20, 30}. -// isPopulated := s.IsPopulated() // isPopulated will be true. +// IsPopulated returns true if the slice is not empty, or false otherwise. func (slice *Slice[T]) IsPopulated() bool { return !slice.IsEmpty() } -// Length returns the number of elements in the Slice. -// -// Example:. -// -// s := &slice.Slice[int]{10, 20, 30, 40, 50}. -// length := s.Length() // length will be 5. +// Length returns the length of the slice. func (slice *Slice[T]) Length() int { return len(*slice) } -// Make empties the slice, sets the new Slice to the length of n, and returns the modified Slice. -// It replaces the existing Slice with a new Slice of the specified length (n) and returns a pointer to the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{10, 20, 30}. -// s.Make(3) // s will be an empty Slice of length 3. +// Make creates a new slice with the specified length and capacity and returns the modified slice. func (slice *Slice[T]) Make(i int) *Slice[T] { - // Create a new slice of the specified length i. *slice = make(Slice[T], i) return slice } -// MakeEach empties the slice, sets the new Slice to the length of n, and populates it by performing a for-each loop on the provided values. -// Finally, it returns a pointer to the modified Slice. -// It replaces the existing Slice with a new Slice of the specified length (n) and populates it by performing a for-each loop on the provided values. -// -// Example:. -// -// s := &slice.Slice[int]{}. -// s.MakeEach(10, 20, 30) // s will be a Slice containing {10, 20, 30}. +// MakeEach creates a new slice with the specified elements and returns the modified slice. func (slice *Slice[T]) MakeEach(v ...T) *Slice[T] { return slice.Make(len(v)).Each(func(i int, _ T) { - // Replace each element in the new slice with the corresponding value from the provided values. slice.Replace(i, v[i]) }) } -// MakeEachReverse empties the slice, sets the new Slice to the length of n, and performs an inverse for-each loop on the provided values,. -// inserting each entry at the appropriate index before returning the modified Slice. -// It replaces the existing Slice with a new Slice of the specified length (n) and populates it by performing an inverse for-each loop on the provided values. -// -// Example:. -// -// s := &slice.Slice[int]{}. -// s.MakeEachReverse(10, 20, 30) // s will be a Slice containing {30, 20, 10}. +// MakeEachReverse creates a new slice with the specified elements in reverse order and returns the modified slice. func (slice *Slice[T]) MakeEachReverse(values ...T) *Slice[T] { currentOffset := 0 return slice.Make(len(values)).EachReverse(func(i int, _ T) { @@ -558,16 +306,7 @@ func (slice *Slice[T]) MakeEachReverse(values ...T) *Slice[T] { }) } -// Map applies the provided function to each element in the slice and creates a new slice containing the modified elements. -// It returns a new Slice[T] containing the transformed elements. The original slice is not modified. -// -// Example:. -// -// numbers := slice.Slice[int]{1, 2, 3, 4, 5}. -// squared := numbers.Map(func(i int, value int) int {. -// return value * value. -// }). -// // squared: [1, 4, 9, 16, 25]. +// Map applies the given function to each element of the slice and returns a new slice with the modified elements. func (slice *Slice[T]) Map(fn func(i int, value T) T) *Slice[T] { s := make(Slice[T], slice.Length()) slice.Each(func(i int, value T) { @@ -576,34 +315,16 @@ func (slice *Slice[T]) Map(fn func(i int, value T) T) *Slice[T] { return &s } -// MapReverse applies the provided function to each element in the slice in reverse order and creates a new slice containing the modified elements. -// It returns a new Slice[T] containing the transformed elements. The original slice is not modified. -// -// Example:. -// -// numbers := slice.Slice[int]{1, 2, 3, 4, 5}. -// reversedSquared := numbers.MapReverse(func(i int, value int) int {. -// return value * value. -// }). -// // reversedSquared: [25, 16, 9, 4, 1]. +// MapReverse applies the given function to each element of the slice in reverse order and returns a new slice with the modified elements. func (slice *Slice[T]) MapReverse(fn func(i int, value T) T) *Slice[T] { - s := &Slice[T]{} + s := make(Slice[T], slice.Length()) slice.EachReverse(func(i int, value T) { - s.Append(fn(i, value)) + s.Replace(i, fn(i, value)) }) - return s + return &s } -// Modify applies the provided function to each element in the slice and modifies the elements in place. -// It iterates over the slice, applying the function to each element along with its index, and replaces the element with the result. -// -// Example:. -// -// numbers := slice.Slice[int]{1, 2, 3, 4, 5}. -// modifiedSlice := numbers.Modify(func(i int, value int) int {. -// return value * 2. -// }). -// // modifiedSlice: [2, 4, 6, 8, 10]. +// Modify applies the given function to each element of the slice and modifies the original slice with the modified elements. func (slice *Slice[T]) Modify(fn func(i int, value T) T) *Slice[T] { slice.Each(func(i int, value T) { slice.Replace(i, fn(i, value)) @@ -611,109 +332,64 @@ func (slice *Slice[T]) Modify(fn func(i int, value T) T) *Slice[T] { return slice } -// Poll removes the first element from the Slice and returns that removed element. -// It removes and returns the first element of the Slice if the Slice is not empty. -// -// Example:. -// -// s := &slice.Slice[int]{10, 20, 30}. -// value := s.Poll() // value will be 10, and s will be [20, 30]. +// ModifyReverse applies the given function to each element of the slice in reverse order and modifies the original slice with the modified elements. +func (slice *Slice[T]) ModifyReverse(fn func(i int, value T) T) *Slice[T] { + slice.EachReverse(func(i int, value T) { + slice.Replace(i, fn(i, value)) + }) + return slice +} + +// Poll removes and returns the first element of the slice, or a zero value if the slice is empty. func (slice *Slice[T]) Poll() T { - var v T + var value T if !slice.IsEmpty() { - v = (*slice)[0] + value = (*slice)[0] *slice = (*slice)[1:] } - return v + return value } -// PollLength removes the first element from the Slice and returns the removed element and the length of the modified Slice. -// It removes and returns the first element of the Slice along with the new length of the modified Slice if the Slice is not empty. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// value, length := s.PollLength() // value will be 1, and length will be 2. +// PollLength removes and returns the first element of the slice and the length of the modified slice. func (slice *Slice[T]) PollLength() (T, int) { return slice.Poll(), slice.Length() } -// PollOK removes and returns the first element from the Slice if it is not empty. -// It checks whether the Slice is populated (not empty) and removes the first element. -// If the Slice is populated, it returns the removed element along with true; otherwise, it returns the zero value for the element and false. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// value, ok := s.PollOK(). -// // 'value' will be 1, and 'ok' will be true as the Slice is not empty. +// PollOK removes and returns the first element of the slice and true if the slice is not empty, or a zero value and false otherwise. func (slice *Slice[T]) PollOK() (T, bool) { - var ( - ok = slice.IsPopulated() - v T - ) - if ok { - v = slice.Poll() + if slice.IsEmpty() { + var value T + return value, false } - return v, ok -} - -// Pop removes and returns the last element from the Slice if it is not empty. -// It checks whether the Slice is populated (not empty) and removes the last element. -// If the Slice is populated, it returns the removed element; otherwise, it returns the zero value for the element. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// value := s.Pop(). -// // 'value' will be 3, and the Slice will become [1, 2]. + return slice.Poll(), true +} + +// Pop removes and returns the last element of the slice, or a zero value if the slice is empty. func (slice *Slice[T]) Pop() T { - var v T + var value T if slice.IsPopulated() { - l := slice.Length() - v = (*slice)[l-1] - *slice = (*slice)[:l-1] + length := slice.Length() + value = (*slice)[length-1] + *slice = (*slice)[:length-1] } - return v + return value } -// PopLength removes the last element from the Slice and returns the removed element along with the length of the modified Slice. -// It removes and returns the last element of the Slice if the Slice is not empty, along with the new length of the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{10, 20, 30}. -// value, length := s.PopLength() // value will be 30, length will be 2, and s will be [10, 20]. +// PopLength removes and returns the last element of the slice and the length of the modified slice. func (slice *Slice[T]) PopLength() (T, int) { return slice.Pop(), slice.Length() } -// PopOK removes the last element from the Slice and returns a boolean indicating the outcome of the transaction. -// It removes the last element from the Slice and returns true if the Slice is not empty; otherwise, it returns false. -// -// Example:. -// -// s := &slice.Slice[int]{10, 20, 30}. -// value, ok := s.PopOK() // value will be 30, ok will be true, and s will be [10, 20]. +// PopOK removes and returns the last element of the slice and true if the slice is not empty, or a zero value and false otherwise. func (slice *Slice[T]) PopOK() (T, bool) { - var ( - ok = slice.IsPopulated() - v T - ) - if ok { - v = slice.Pop() + if slice.IsEmpty() { + var value T + return value, false } - return v, ok + return slice.Pop(), true } -// Precatenate merges the elements from the argument Slice to the head of the receiver Slice and returns the modified Slice. -// If the provided Slice (s) is not nil, it prepends its elements to the receiver Slice and returns a pointer to the modified Slice. -// -// Example:. -// -// s1 := &slice.Slice[int]{1, 2, 3}. -// s2 := &slice.Slice[int]{4, 5}. -// s1.Precatenate(s2) // s1 will be [4, 5, 1, 2, 3]. +// Precatenate concatenates the given slice with the original slice and returns the modified slice. func (slice *Slice[T]) Precatenate(s *Slice[T]) *Slice[T] { if s != nil { slice.Prepend((*s)...) @@ -721,56 +397,24 @@ func (slice *Slice[T]) Precatenate(s *Slice[T]) *Slice[T] { return slice } -// PrecatenateFunc prepends elements from another Slice to the head of the receiver Slice based on a provided predicate function. -// It iterates over each element in the source slice, invoking the provided function. If the function returns 'true' for an element,. -// that element is prepended to the receiver slice. If it returns 'false', the element is skipped. -// -// Example:. -// -// s1 := &slice.Slice[int]{1, 2, 3}. -// s2 := &slice.Slice[int]{4, 5, 6}. -// result := s1.PrecatenateFunc(s2, func(i int, value int) bool {. -// return value%2 == 0. -// }) // s1 will be modified to [4, 6, 2, 1, 3], and 'result' will be a pointer to 's1'. +// PrecatenateFunc concatenates values based on the provided function and returns the modified slice. func (slice *Slice[T]) PrecatenateFunc(s *Slice[T], fn func(i int, value T) bool) *Slice[T] { - return slice.PrependFunc(fn, (*s)...) + return slice.PrependFunc(*s, fn) } -// PrecatenateLength merges the elements from the argument Slice to the head of the receiver Slice and returns the length of the modified Slice. -// If the provided Slice (s) is not nil, it prepends its elements to the receiver Slice and returns the length of the modified Slice. -// -// Example:. -// -// s1 := &slice.Slice[int]{1, 2, 3}. -// s2 := &slice.Slice[int]{4, 5}. -// length := s1.PrecatenateLength(s2) // length will be 5, and s1 will be [4, 5, 1, 2, 3]. +// PrecatenateLength concatenates the given slice with the original slice and returns the length of the modified slice. func (slice *Slice[T]) PrecatenateLength(s *Slice[T]) int { return slice.Precatenate(s).Length() } -// Prepend adds one element to the head of the Slice and returns the modified Slice. -// It adds the specified values to the beginning of the existing Slice and returns a pointer to the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{2, 3}. -// s.Prepend(1) // s will be [1, 2, 3]. +// Prepend adds the given values to the beginning of the slice and returns the modified slice. func (slice *Slice[T]) Prepend(values ...T) *Slice[T] { *slice = append(values, *slice...) return slice } -// PrependFunc prepends elements to the head of the receiver Slice based on a provided predicate function. -// It iterates over each element in the 'values' argument, invoking the provided function. If the function returns 'true' for an element,. -// that element is prepended to the receiver slice. If it returns 'false', the element is skipped. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// result := s.PrependFunc(func(i int, value int) bool {. -// return value%2 == 0. -// }, 4, 5, 6) // 's' will be modified to [6, 4, 2, 1, 3], and 'result' will be a pointer to 's'. -func (slice *Slice[T]) PrependFunc(fn func(i int, value T) bool, values ...T) *Slice[T] { +// PrependFunc adds values to the beginning of the slice based on the provided function and returns the modified slice. +func (slice *Slice[T]) PrependFunc(values []T, fn func(i int, value T) bool) *Slice[T] { s := &Slice[T]{} for i, value := range values { if fn(i, value) { @@ -781,29 +425,12 @@ func (slice *Slice[T]) PrependFunc(fn func(i int, value T) bool, values ...T) *S return slice } -// PrependLength adds n elements to the head of the Slice and returns the length of the modified Slice. -// It adds the specified values to the beginning of the existing Slice and returns the length of the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{2, 3}. -// length := s.PrependLength(1, 0) // length will be 4, and s will be [1, 0, 2, 3]. +// PrependLength adds values to the beginning of the slice and returns the length of the modified slice. func (slice *Slice[T]) PrependLength(values ...T) int { return slice.Prepend(values...).Length() } -// Reduce applies the provided function to each element in the slice and reduces the elements to a single value. -// It iterates over the slice, applying the function to each element along with its index and the current result value,. -// and accumulates the result. The result of the previous function call is passed as the third argument to the next function call. -// It returns the final reduced value. -// -// Example:. -// -// numbers := slice.Slice[int]({1, 2, 3, 4, 5}). -// sum := numbers.Reduce(func(i int, currentValue int, resultValue int) int {. -// return resultValue + currentValue. -// }). -// // sum: 15 (1 + 2 + 3 + 4 + 5). +// Reduce applies the given function to each element of the slice and returns the reduced result value. func (slice *Slice[T]) Reduce(fn func(i int, currentValue T, resultValue T) T) T { var resultValue T slice.Each(func(i int, currentValue T) { @@ -812,17 +439,7 @@ func (slice *Slice[T]) Reduce(fn func(i int, currentValue T, resultValue T) T) T return resultValue } -// ReduceReverse iterates over the slice in reverse order and reduces the elements into a single value using the provided function. -// It starts from the last element and accumulates the result by applying the function to each element along with its index and the current accumulated result. -// The result of each iteration becomes the input for the next iteration. -// -// Example:. -// -// numbers := slice.Slice[int]{1, 2, 3, 4, 5}. -// sum := numbers.ReduceReverse(func(i int, currentValue, resultValue int) int {. -// return currentValue + resultValue. -// }). -// // sum: 15 (sum of all elements in the slice). +// ReduceReverse applies the given function to each element of the slice in reverse order and returns the reduced result value. func (slice *Slice[T]) ReduceReverse(fn func(i int, currentValue T, resultValue T) T) T { var resultValue T slice.EachReverse(func(i int, currentValue T) { @@ -831,77 +448,24 @@ func (slice *Slice[T]) ReduceReverse(fn func(i int, currentValue T, resultValue return resultValue } -// Replace changes the contents of the Slice at the argument index if it is in bounds. -// It replaces the element at the specified index with the provided value if the index is within bounds and returns true. -// Otherwise, it returns false. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// ok := s.Replace(1, 4) // ok will be true, and s will be [1, 4, 3]. +// Replace replaces the element at the specified index with the given value and returns true if the index is valid, or false otherwise. func (slice *Slice[T]) Replace(i int, value T) bool { - ok := slice.Bounds(i) - if ok { + if slice.Bounds(i) { (*slice)[i] = value + return true } - return ok + return false } -// Reverse reverses the Slice in linear time and returns the modified Slice. -// It reverses the order of elements in the Slice and returns a pointer to the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// s.Reverse() // s will be [3, 2, 1]. +// Reverse reverses the elements of the slice and returns the modified slice. func (slice *Slice[T]) Reverse() *Slice[T] { - var ( - i = 0 - j = slice.Length() - 1 - ) - for i < j { + for i, j := 0, slice.Length()-1; i < j; i, j = i+1, j-1 { slice.Swap(i, j) - i = i + 1 - j = j - 1 } return slice } -// Set returns a unique slice, removing duplicate elements that have the same hash value. -// Returns the modified Slice at the end of the iteration. -// It removes duplicate elements from the slice, keeping only the first occurrence of each unique element. -// Returns a pointer to the modified Slice with unique elements. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 2, 3, 3, 3}. -// s.Set() // s will be [1, 2, 3]. -func (slice *Slice[T]) Set() *Slice[T] { - var ( - k string - m = map[string]bool{} - ok bool - s = &Slice[T]{} - ) - slice.Each(func(_ int, value T) { - k = fmt.Sprintf("%v", value) // TODO: Check if there is a better way to generate key. - _, ok = m[k] - if !ok { - s.Append(value) - } - m[k] = true - }) - *slice = *s - return slice -} - -// Shuffle randomly shuffles the elements of the Slice and returns the modified Slice. -// It shuffles the elements of the Slice in a random order and returns a pointer to the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// s.Shuffle() // s will be a random permutation of [1, 2, 3, 4, 5]. +// Shuffle shuffles the elements of the slice and returns the modified slice. func (slice *Slice[T]) Shuffle() *Slice[T] { rand.Shuffle(slice.Length(), func(i, j int) { slice.Swap(i, j) @@ -909,65 +473,68 @@ func (slice *Slice[T]) Shuffle() *Slice[T] { return slice } -// Slice slices the Slice from i to j and returns a new Slice. -// It slices the Slice from the specified start (i) index to the end (j) index (inclusive),. -// and returns a pointer to the new Slice. -// -// Example:. -// -// numbers := slice.Slice[int]{1, 2, 3, 4, 5}. -// // Create a new slice containing elements at indexes 1 to 3 from the original slice. -// subset := numbers.Slice(1, 4). -// // Resulting subset: [2, 3, 4]. +// Slice returns a new slice containing the elements from index i to j (inclusive) of the original slice. func (slice *Slice[T]) Slice(i int, j int) *Slice[T] { if j < i { i, j = j, i } - s := (*slice)[i : j+1] // Include the element at index j. + s := (*slice)[i : j+1] return &s } -// SortFunc sorts the elements of the slice based on a custom comparison function. -// Takes a comparison function that takes two indices (i, j) and two elements (a, b) of type T and returns true if element a should come before element b in the sorted order. If fn returns true, it means a is considered less than b in the sorting order. -// -// s := &slice.Slice[int]{5, 2, 8, 1, 9}. -// s.SortFunc(func(i, j int, a, b int) bool {. -// return a < b. -// }). +// SortFunc sorts the elements of the slice based on the provided comparison function and returns the modified slice. func (slice *Slice[T]) SortFunc(fn func(i int, j int, a T, b T) bool) *Slice[T] { - v := *slice // Copy the slice to a new variable. - sort.Slice(v, func(i int, j int) bool { - return fn(i, j, v[i], v[j]) // Use the copied slice (v) instead of slice. + s := *slice // Copy the slice to a new variable. + sort.Slice(s, func(i int, j int) bool { + return fn(i, j, s[i], s[j]) // Use the copied slice (v) instead of slice. }) - *slice = v // Update the original slice with the sorted copy. + *slice = s // Update the original slice with the sorted copy. return slice } -// Splice slices the Slice from i to j and returns the modified Slice. -// It slices the Slice from the specified start (i) index to the end (j) index (inclusive),. -// and returns a pointer to the modified Slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3, 4, 5}. -// s.Splice(1, 3) // s will be [2, 3, 4]. +// Splice removes elements from the slice starting from index i to j (inclusive) and returns the modified slice. func (slice *Slice[T]) Splice(i int, j int) *Slice[T] { if j < i { i, j = j, i } if slice.Bounds(i) && slice.Bounds(j) { - *slice = (*slice)[i : j+1] // Include the element at index j. + *slice = (*slice)[i : j+1] } return slice } -// Swap moves element i to j and j to i. -// If both indices (i and j) are within bounds, it swaps the elements at those positions in the Slice. -// -// Example:. -// -// s := &slice.Slice[int]{1, 2, 3}. -// s.Swap(0, 2) // s will be [3, 2, 1]. +// Split divides the slice into two slices at the specified index and returns the two new slices. +func (slice *Slice[T]) Split(i int) (*Slice[T], *Slice[T]) { + if !slice.Bounds(i) { + return nil, nil + } + firstSlice, secondSlice := (*slice)[:i], (*slice)[i:] + return &firstSlice, &secondSlice +} + +// SplitFunc divides the slice into two slices based on the provided function and returns the two new slices. +func (slice *Slice[T]) SplitFunc(fn func(i int, value T) bool) (*Slice[T], *Slice[T]) { + firstSlice, secondSlice := &Slice[T]{}, &Slice[T]{} + slice.Each(func(i int, value T) { + if fn(i, value) { + firstSlice.Append(value) + } else { + secondSlice.Append(value) + } + }) + return firstSlice, secondSlice +} + +// SplitOK divides the slice into two slices at the specified index and returns the two new slices, or false if the index is invalid. +func (slice *Slice[T]) SplitOK(i int) (*Slice[T], *Slice[T], bool) { + if !slice.Bounds(i) { + return nil, nil, false + } + firstSlice, secondSlice := (*slice)[:i], (*slice)[i:] + return &firstSlice, &secondSlice, true +} + +// Swap swaps the elements at the specified indices in the slice. func (slice *Slice[T]) Swap(i int, j int) { if slice.Bounds(i) && slice.Bounds(j) { (*slice)[i], (*slice)[j] = (*slice)[j], (*slice)[i] @@ -975,12 +542,6 @@ func (slice *Slice[T]) Swap(i int, j int) { } // New creates a new instance of the Slice[T] type and initializes it with the provided values. -// It allows you to create a new Slice and populate it with the specified elements. -// -// Example:. -// -// s := New[int](1, 2, 3, 4, 5). -// // 's' will be a pointer to a new Slice containing [1, 2, 3, 4, 5]. func New[T any](values ...T) *Slice[T] { return (&Slice[T]{}).Append(values...) } diff --git a/slice_test.go b/slice_test.go index 0792e67..42a213b 100644 --- a/slice_test.go +++ b/slice_test.go @@ -7,1755 +7,1159 @@ import ( "github.com/lindsaygelle/slice" ) -// TestAppend tests Slice.Append. func TestAppend(t *testing.T) { // Test case 1: Append values to an empty slice. - input := &slice.Slice[int]{} - expectedOutput := &slice.Slice[int]{1, 2, 3} - input.Append(1, 2, 3) + s := &slice.Slice[int]{} + s.Append(1, 2, 3) - if !reflect.DeepEqual(input, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, input) + expected := &slice.Slice[int]{1, 2, 3} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } // Test case 2: Append values to a non-empty slice. - input = &slice.Slice[int]{1, 2, 3} - expectedOutput = &slice.Slice[int]{1, 2, 3, 4, 5} - input.Append(4, 5) + s = &slice.Slice[int]{1, 2} + s.Append(3, 4, 5) - if !reflect.DeepEqual(input, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, input) + expected = &slice.Slice[int]{1, 2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestAppendFunc tests Slice.AppendFunc. func TestAppendFunc(t *testing.T) { - // Test case 1: Append even numbers. - input := &slice.Slice[int]{} - input.AppendFunc(func(i int, value int) bool { - return value%2 == 0 // Append even numbers to the Slice. - }, 1, 2, 3, 4, 5) + // Test case 1: Append values to an empty slice based on a function. + s := &slice.Slice[int]{} + fn := func(i int, value int) bool { + return value%2 == 0 + } + s.AppendFunc([]int{1, 2, 3, 4, 5}, fn) - expectedOutput := &slice.Slice[int]{2, 4} - if !reflect.DeepEqual(input, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, input) + expected := &slice.Slice[int]{2, 4} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - // Test case 2: Append odd numbers. - input = &slice.Slice[int]{} - input.AppendFunc(func(i int, value int) bool { - return value%2 != 0 // Append odd numbers to the Slice. - }, 1, 2, 3, 4, 5) + // Test case 2: Append values to a non-empty slice based on a function. + s = &slice.Slice[int]{1, 2, 3} + fn = func(i int, value int) bool { + return value > 1 + } + s.AppendFunc([]int{1, 2, 3, 4, 5}, fn) - expectedOutput = &slice.Slice[int]{1, 3, 5} - if !reflect.DeepEqual(input, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, input) + expected = &slice.Slice[int]{1, 2, 3, 2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestAppendLength tests Slice.AppendLength. func TestAppendLength(t *testing.T) { - // Test case 1: Append values to an empty slice. - input := &slice.Slice[int]{} - length := input.AppendLength(1, 2, 3) + // Test case 1: Append values to an empty slice and check the length. + s := &slice.Slice[int]{} + length := s.AppendLength(1, 2, 3) - expectedOutput := 3 - if length != expectedOutput { - t.Errorf("Expected length %d, but got %d", expectedOutput, length) + expected := &slice.Slice[int]{1, 2, 3} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - - // Test case 2: Append values to a non-empty slice. - input = &slice.Slice[int]{1, 2, 3} - length = input.AppendLength(4, 5) - - expectedOutput = 5 - if length != expectedOutput { - t.Errorf("Expected length %d, but got %d", expectedOutput, length) + if length != 3 { + t.Errorf("Expected length 3, but got %d", length) } - // Test case 3: Append no values (length should remain the same). - input = &slice.Slice[int]{1, 2, 3} - length = input.AppendLength() + // Test case 2: Append values to a non-empty slice and check the length. + s = &slice.Slice[int]{1, 2} + length = s.AppendLength(3, 4, 5) - expectedOutput = 3 - if length != expectedOutput { - t.Errorf("Expected length %d, but got %d", expectedOutput, length) + expected = &slice.Slice[int]{1, 2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) + } + if length != 5 { + t.Errorf("Expected length 5, but got %d", length) } } -// TestBounds tests Slice.Bounds. func TestBounds(t *testing.T) { - // Test case 1: Index within bounds. - input := &slice.Slice[int]{1, 2, 3} - inBounds := input.Bounds(1) - expectedInBounds := true - if inBounds != expectedInBounds { - t.Errorf("Expected %t, but got %t", expectedInBounds, inBounds) - } - - // Test case 2: Index out of bounds (negative index). - outOfBounds := input.Bounds(-1) - expectedOutOfBounds := false - if outOfBounds != expectedOutOfBounds { - t.Errorf("Expected %t, but got %t", expectedOutOfBounds, outOfBounds) - } - - // Test case 3: Index out of bounds (index greater than the length of the slice). - outOfBounds = input.Bounds(5) - if outOfBounds != expectedOutOfBounds { - t.Errorf("Expected %t, but got %t", expectedOutOfBounds, outOfBounds) + // Test case 1: Check index within bounds. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + result := s.Bounds(2) + if !result { + t.Errorf("Expected true, but got false") } - // Test case 4: Index within bounds (edge case: index equal to the length of the slice). - inBounds = input.Bounds(3) - expectedInBounds = false // Index 3 is out of bounds for a slice with length 3. - if inBounds != expectedInBounds { - t.Errorf("Expected %t, but got %t", expectedInBounds, inBounds) + // Test case 2: Check index out of bounds. + result = s.Bounds(10) + if result { + t.Errorf("Expected false, but got true") } } -// TestClone tests Slice.Clone. func TestClone(t *testing.T) { // Test case 1: Clone an empty slice. - emptySlice := &slice.Slice[int]{} - clonedEmptySlice := emptySlice.Clone() + s := &slice.Slice[int]{} + clone := s.Clone() - if !reflect.DeepEqual(emptySlice, clonedEmptySlice) { - t.Errorf("Clone of an empty slice should be empty, but got %v", clonedEmptySlice) + if !reflect.DeepEqual(s, clone) { + t.Errorf("Expected %v, but got %v", s, clone) } // Test case 2: Clone a non-empty slice. - numbers := &slice.Slice[int]{1, 2, 3, 4, 5} - clonedSlice := numbers.Clone() - - // Expected cloned slice: [1, 2, 3, 4, 5]. - expected := []int{1, 2, 3, 4, 5} - - // Modify the cloned slice to check if it is independent of the original slice. - clonedSlice.Append(6) + s = &slice.Slice[int]{1, 2, 3} + clone = s.Clone() - // Check if the original slice remains unchanged. - if reflect.DeepEqual(numbers, expected) { - t.Errorf("Original slice should remain unchanged after cloning, but got %v", numbers) + if !reflect.DeepEqual(s, clone) { + t.Errorf("Expected %v, but got %v", s, clone) } } -// TestConcatenate tests Slice.Concatenate. func TestConcatenate(t *testing.T) { - // Test case 1: Concatenating with a non-nil slice. - s1 := &slice.Slice[int]{1, 2, 3} - s2 := &slice.Slice[int]{4, 5} - s1.Concatenate(s2) + // Test case 1: Concatenate with nil slice. + s := &slice.Slice[int]{1, 2, 3} + result := s.Concatenate(nil) - expectedOutput := &slice.Slice[int]{1, 2, 3, 4, 5} - if !reflect.DeepEqual(s1, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s1) + expected := &slice.Slice[int]{1, 2, 3} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - - // Test case 2: Concatenating with a nil slice (no modification should occur). - s1 = &slice.Slice[int]{1, 2, 3} - s2 = &slice.Slice[int]{} // nil slice. - s1.Concatenate(s2) - - expectedOutput = &slice.Slice[int]{1, 2, 3} - if !reflect.DeepEqual(s1, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s1) + if result != s { + t.Errorf("Expected result to be the same slice, but got a different slice") } - // Test case 3: Concatenating with an empty slice. - s1 = &slice.Slice[int]{1, 2, 3} - s2 = &slice.Slice[int]{} // empty slice. - s1.Concatenate(s2) + // Test case 2: Concatenate with a non-empty slice. + s = &slice.Slice[int]{1, 2} + other := &slice.Slice[int]{3, 4, 5} + result = s.Concatenate(other) - expectedOutput = &slice.Slice[int]{1, 2, 3} // no modification should occur. - if !reflect.DeepEqual(s1, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s1) + expected = &slice.Slice[int]{1, 2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) + } + if result != s { + t.Errorf("Expected result to be the same slice, but got a different slice") } } -// TestConcatenateFunc tests Slice.ConcatenateFunc. func TestConcatenateFunc(t *testing.T) { - // Test case 1: Concatenating with a non-nil slice, filtering even numbers. - s1 := &slice.Slice[int]{1, 2, 3} - s2 := &slice.Slice[int]{4, 5, 6} - s1.ConcatenateFunc(s2, func(i int, value int) bool { + // Test case 1: Concatenate with nil slice using a function. + s := &slice.Slice[int]{1, 2, 3} + fn := func(i int, value int) bool { return value%2 == 0 - }) - - expectedOutput := &slice.Slice[int]{1, 2, 3, 4, 6} - if !reflect.DeepEqual(s1, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s1) } + result := s.ConcatenateFunc(nil, fn) - // Test case 2: Concatenating with a nil slice (no modification should occur). - s1 = &slice.Slice[int]{1, 2, 3} - s2 = &slice.Slice[int]{} // nil slice. - s1.ConcatenateFunc(s2, func(i int, value int) bool { - return true - }) - - expectedOutput = &slice.Slice[int]{1, 2, 3} - if !reflect.DeepEqual(s1, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s1) + expected := &slice.Slice[int]{1, 2, 3} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) + } + if result != s { + t.Errorf("Expected result to be the same slice, but got a different slice") } - // Test case 3: Concatenating with an empty slice (no modification should occur). - s1 = &slice.Slice[int]{1, 2, 3} - s2 = &slice.Slice[int]{} // empty slice. - s1.ConcatenateFunc(s2, func(i int, value int) bool { - return true - }) + // Test case 2: Concatenate with a non-empty slice using a function. + s = &slice.Slice[int]{1, 2} + other := &slice.Slice[int]{3, 4, 5} + fn = func(i int, value int) bool { + return value > 3 + } + result = s.ConcatenateFunc(other, fn) - expectedOutput = &slice.Slice[int]{1, 2, 3} - if !reflect.DeepEqual(s1, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s1) + expected = &slice.Slice[int]{1, 2, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) + } + if result != s { + t.Errorf("Expected result to be the same slice, but got a different slice") } } -// TestConcatenateLength tests Slice.ConcatenateLength. func TestConcatenateLength(t *testing.T) { - // Test case 1: Concatenating with a non-nil slice. - s1 := &slice.Slice[int]{1, 2, 3} - s2 := &slice.Slice[int]{4, 5} - length := s1.ConcatenateLength(s2) + // Test case 1: Concatenate with nil slice and check the length. + s := &slice.Slice[int]{1, 2, 3} + length := s.ConcatenateLength(nil) - expectedOutput := 5 - if length != expectedOutput { - t.Errorf("Expected length %d, but got %d", expectedOutput, length) + expected := &slice.Slice[int]{1, 2, 3} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - - // Test case 2: Concatenating with a nil slice (length should remain the same). - s1 = &slice.Slice[int]{1, 2, 3} - s2 = &slice.Slice[int]{} // nil slice. - length = s1.ConcatenateLength(s2) - - expectedOutput = 3 - if length != expectedOutput { - t.Errorf("Expected length %d, but got %d", expectedOutput, length) + if length != 3 { + t.Errorf("Expected length 3, but got %d", length) } - // Test case 3: Concatenating with an empty slice (length should remain the same). - s1 = &slice.Slice[int]{1, 2, 3} - s2 = &slice.Slice[int]{} // empty slice. - length = s1.ConcatenateLength(s2) + // Test case 2: Concatenate with a non-empty slice and check the length. + s = &slice.Slice[int]{1, 2} + other := &slice.Slice[int]{3, 4, 5} + length = s.ConcatenateLength(other) - expectedOutput = 3 - if length != expectedOutput { - t.Errorf("Expected length %d, but got %d", expectedOutput, length) + expected = &slice.Slice[int]{1, 2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) + } + if length != 5 { + t.Errorf("Expected length 5, but got %d", length) } } -// TestContains tests Slice.Contains. func TestContains(t *testing.T) { - // Test case 1: Value is present in the slice. - s := &slice.Slice[string]{"apple", "banana", "cherry"} - containsBanana := s.Contains("banana") - expectedResult := true - - if containsBanana != expectedResult { - t.Errorf("Expected %t, but got %t", expectedResult, containsBanana) + // Test case 1: Check if value is present in the slice. + s := &slice.Slice[string]{"apple", "banana", "orange"} + result := s.Contains("banana") + if !result { + t.Errorf("Expected true, but got false") } - // Test case 2: Value is not present in the slice. - containsGrapes := s.Contains("grapes") - expectedResult = false - - if containsGrapes != expectedResult { - t.Errorf("Expected %t, but got %t", expectedResult, containsGrapes) - } - - // Test case 3: Value is present in an empty slice. - emptySlice := &slice.Slice[string]{} - containsEmpty := emptySlice.Contains("") - expectedResult = false - - if containsEmpty != expectedResult { - t.Errorf("Expected %t, but got %t", expectedResult, containsEmpty) + // Test case 2: Check if value is not present in the slice. + result = s.Contains("grape") + if result { + t.Errorf("Expected false, but got true") } } -// TestContainsMany tests Slice.ContainsMany. func TestContainsMany(t *testing.T) { - // Test case 1: Multiple values are present in the slice. + // Test case 1: Check multiple values present in the slice. s := &slice.Slice[int]{1, 2, 3, 4, 5} result := s.ContainsMany(2, 4, 6) - expectedResult := &slice.Slice[bool]{true, true, false} - - if !reflect.DeepEqual(result, expectedResult) { - t.Errorf("Expected %v, but got %v", expectedResult, result) - } - - // Test case 2: All values are present in the slice. - result = s.ContainsMany(2, 4, 1) - expectedResult = &slice.Slice[bool]{true, true, true} - if !reflect.DeepEqual(result, expectedResult) { - t.Errorf("Expected %v, but got %v", expectedResult, result) + expected := &slice.Slice[bool]{true, true, false} + if !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %v, but got %v", expected, result) } - // Test case 3: None of the values are present in the slice. - result = s.ContainsMany(6, 7, 8) - expectedResult = &slice.Slice[bool]{false, false, false} + // Test case 2: Check multiple values, some not present in the slice. + result = s.ContainsMany(3, 5, 7) - if !reflect.DeepEqual(result, expectedResult) { - t.Errorf("Expected %v, but got %v", expectedResult, result) + expected = &slice.Slice[bool]{true, true, false} + if !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %v, but got %v", expected, result) } +} - // Test case 4: Empty slice (no values should be found). - emptySlice := &slice.Slice[int]{} - result = emptySlice.ContainsMany(1, 2, 3) - expectedResult = &slice.Slice[bool]{false, false, false} +func TestDeduplicate(t *testing.T) { + // Test case: Deduplicate a slice with duplicate values. + s := &slice.Slice[int]{1, 2, 2, 3, 4, 4, 5} + s.Deduplicate() - if !reflect.DeepEqual(result, expectedResult) { - t.Errorf("Expected %v, but got %v", expectedResult, result) + expected := &slice.Slice[int]{1, 2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestDelete tests Slice.Delete. func TestDelete(t *testing.T) { - // Test case 1: Delete element within bounds. + // Test case: Delete a value at a specific index. s := &slice.Slice[int]{1, 2, 3, 4, 5} s.Delete(2) - expectedOutput := &slice.Slice[int]{1, 2, 4, 5} - if !reflect.DeepEqual(s, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s) - } - - // Test case 2: Delete element out of bounds (no modification should occur). - s = &slice.Slice[int]{1, 2, 3, 4, 5} - s.Delete(5) // Index out of bounds. - - expectedOutput = &slice.Slice[int]{1, 2, 3, 4, 5} // No modification expected. - if !reflect.DeepEqual(s, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s) - } - - // Test case 3: Delete element out of bounds (negative index, no modification should occur). - s = &slice.Slice[int]{1, 2, 3, 4, 5} - s.Delete(-1) // Index out of bounds. - - expectedOutput = &slice.Slice[int]{1, 2, 3, 4, 5} // No modification expected. - if !reflect.DeepEqual(s, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s) + expected := &slice.Slice[int]{1, 2, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestDeleteFunc tests Slice.DeleteFunc. func TestDeleteFunc(t *testing.T) { - // Test case 1: Delete even numbers. + // Test case: Delete values based on a function. s := &slice.Slice[int]{1, 2, 3, 4, 5} - even := func(i int, value int) bool { return value%2 == 0 } - s.DeleteFunc(even) - - expectedOutput := &slice.Slice[int]{1, 3, 5} - if !reflect.DeepEqual(s, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s) - } - - // Test case 2: Delete odd numbers. - s = &slice.Slice[int]{1, 2, 3, 4, 5} - odd := func(i int, value int) bool { return value%2 != 0 } - s.DeleteFunc(odd) - - expectedOutput = &slice.Slice[int]{2, 4} - if !reflect.DeepEqual(s, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s) + fn := func(i int, value int) bool { + return value%2 == 0 } + s.DeleteFunc(fn) - // Test case 3: Delete all elements (empty slice). - s = &slice.Slice[int]{1, 2, 3, 4, 5} - all := func(i int, value int) bool { return true } - s.DeleteFunc(all) - - expectedOutput = &slice.Slice[int]{} - if !reflect.DeepEqual(s, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s) + expected := &slice.Slice[int]{1, 3, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestDeleteLength tests Slice.DeleteLength. func TestDeleteLength(t *testing.T) { - // Test case 1: Delete element within bounds. + // Test case: Delete a value at a specific index and check the length. s := &slice.Slice[int]{1, 2, 3, 4, 5} - newLength := s.DeleteLength(2) - - expectedOutput := 4 - if newLength != expectedOutput { - t.Errorf("Expected new length %d, but got %d", expectedOutput, newLength) - } + length := s.DeleteLength(2) - // Test case 2: Delete element out of bounds (no modification should occur). - s = &slice.Slice[int]{1, 2, 3, 4, 5} - newLength = s.DeleteLength(5) // Index out of bounds. - - expectedOutput = 5 // Length remains the same. - if newLength != expectedOutput { - t.Errorf("Expected new length %d, but got %d", expectedOutput, newLength) + expected := &slice.Slice[int]{1, 2, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - - // Test case 3: Delete element out of bounds (negative index, no modification should occur). - s = &slice.Slice[int]{1, 2, 3, 4, 5} - newLength = s.DeleteLength(-1) // Index out of bounds. - - expectedOutput = 5 // Length remains the same. - if newLength != expectedOutput { - t.Errorf("Expected new length %d, but got %d", expectedOutput, newLength) + if length != 4 { + t.Errorf("Expected length 4, but got %d", length) } } -// TestDeleteOK tests Slice.DeleteOK. func TestDeleteOK(t *testing.T) { - // Test case 1: Delete element within bounds (successful deletion). + // Test case 1: Delete a value at a specific index successfully. s := &slice.Slice[int]{1, 2, 3, 4, 5} - deleted := s.DeleteOK(2) - - expectedOutput := true - if deleted != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, deleted) - } - - expectedSlice := &slice.Slice[int]{1, 2, 4, 5} - if !s.Equal(expectedSlice) { - t.Errorf("Expected %v, but got %v", expectedSlice, s) - } - - // Test case 2: Delete element out of bounds (no modification should occur). - s = &slice.Slice[int]{1, 2, 3, 4, 5} - deleted = s.DeleteOK(5) // Index out of bounds. - - expectedOutput = false - if deleted != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, deleted) + result := s.DeleteOK(2) + if !result { + t.Errorf("Expected true, but got false") } - expectedSlice = &slice.Slice[int]{1, 2, 3, 4, 5} // No modification expected. - if !s.Equal(expectedSlice) { - t.Errorf("Expected %v, but got %v", expectedSlice, s) + expected := &slice.Slice[int]{1, 2, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - // Test case 3: Delete element out of bounds (negative index, no modification should occur). - s = &slice.Slice[int]{1, 2, 3, 4, 5} - deleted = s.DeleteOK(-1) // Index out of bounds. - - expectedOutput = false - if deleted != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, deleted) - } - - expectedSlice = &slice.Slice[int]{1, 2, 3, 4, 5} // No modification expected. - if !s.Equal(expectedSlice) { - t.Errorf("Expected %v, but got %v", expectedSlice, s) + // Test case 2: Delete a value at an out-of-bounds index. + result = s.DeleteOK(10) + if result { + t.Errorf("Expected false, but got true") } } -// TestEach tests Slice.Each. -func TestEach(t *testing.T) { +func TestDeleteUnsafe(t *testing.T) { + // Test case: Delete a value at a specific index without bounds checking. s := &slice.Slice[int]{1, 2, 3, 4, 5} - s.Each(func(i int, value int) { - if ok := (*s)[i] == value; !ok { - t.Fatalf("*Slice[%d] != %d", i, value) - } - }) -} + s.DeleteUnsafe(2) -// TestEachBreak tests Slice.EachBreak. -func TestEachBreak(t *testing.T) { - s := &slice.Slice[int]{1, 2, 3, 4, 5} - count := 0 - s.EachBreak(func(i int, value int) bool { - count = count + 1 - return false - }) - if ok := count == 1; !ok { - t.Fatalf("count != 1") + expected := &slice.Slice[int]{1, 2, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestEachReverse tests Slice.EachReverse. -func TestEachReverse(t *testing.T) { +func TestEach(t *testing.T) { + // Test case: Apply a function to each element in the slice. s := &slice.Slice[int]{1, 2, 3, 4, 5} - s.EachReverse(func(i int, value int) { - if ok := (*s)[i] == value; !ok { - t.Fatalf("*Slice[%d] != %d", i, value) - } - }) -} + var sum int + fn := func(i int, value int) { + sum += value + } + s.Each(fn) -// TestEachReverseBreak tests Slice.EachReverseBreak. -func TestEachReverseBreak(t *testing.T) { - s := &slice.Slice[int]{1, 2, 3, 4, 5} - count := 0 - s.EachReverseBreak(func(i int, value int) bool { - count = count + 1 - return false - }) - if ok := count == 1; !ok { - t.Fatalf("count != 1") + if sum != 15 { + t.Errorf("Expected sum 15, but got %d", sum) } } -// TestEqual tests Slice.Equal. -func TestEqual(t *testing.T) { - // Test case 1: Equal slices. - slice1 := &slice.Slice[int]{1, 2, 3} - slice2 := &slice.Slice[int]{1, 2, 3} - - equal := slice1.Equal(slice2) - expectedOutput := true - if equal != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, equal) +func TestEachBreak(t *testing.T) { + // Test case 1: Apply a function to each element until the function returns false. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + var sum int + fn := func(i int, value int) bool { + sum += value + return value%2 != 0 } + s.EachBreak(fn) - // Test case 2: Unequal slices (different length). - slice3 := &slice.Slice[int]{1, 2} - equal = slice1.Equal(slice3) - expectedOutput = false - if equal != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, equal) + if sum != 3 { + t.Errorf("Expected sum 3, but got %d", sum) } - // Test case 3: Unequal slices (different elements). - slice4 := &slice.Slice[int]{1, 2, 4} - equal = slice1.Equal(slice4) - expectedOutput = false - if equal != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, equal) + // Test case 2: Apply a function to each element without breaking. + sum = 0 + fn = func(i int, value int) bool { + sum += value + return true } + s.EachBreak(fn) - // Test case 4: Equal slices with different types (should return false). - slice5 := &slice.Slice[interface{}]{1, uint(2), 3} - slice6 := &slice.Slice[interface{}]{1, 2, 3} - equal = slice5.Equal(slice6) - expectedOutput = false - if equal != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, equal) + if sum != 15 { + t.Errorf("Expected sum 15, but got %d", sum) } } -// TestEqualFunc test Slice.EqualFunc. -func TestEqualFunc(t *testing.T) { - // Test case 1: Equal slices using a custom comparison function. - slice1 := &slice.Slice[int]{1, 2, 3} - slice2 := &slice.Slice[int]{2, 4, 6} - customEqual := func(i int, value1, value2 int) bool { - return value1*2 == value2 +func TestEachOK(t *testing.T) { + // Test case 1: Apply a function to each element until the function returns false and check the result. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + var sum int + fn := func(i int, value int) bool { + sum += value + return value%2 != 0 } + result := s.EachOK(fn) - equal := slice1.EqualFunc(slice2, customEqual) - expectedOutput := true - if equal != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, equal) + if sum != 3 { + t.Errorf("Expected sum 3, but got %d", sum) } - - // Test case 2: Unequal slices using a custom comparison function. - slice3 := &slice.Slice[int]{1, 3, 5} - equal = slice1.EqualFunc(slice3, customEqual) - expectedOutput = false - if equal != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, equal) + if result { + t.Errorf("Expected false, but got true") } - // Test case 3: Equal slices with different values. - slice4 := &slice.Slice[int]{9, 12, 51} - equal = slice1.EqualFunc(slice4, func(i int, value1, value2 int) bool { - return value1*2 == value2 - }) - expectedOutput = false - if equal != expectedOutput { - t.Errorf("Expected %t, but got %t", expectedOutput, equal) + // Test case 2: Apply a function to each element without breaking and check the result. + sum = 0 + fn = func(i int, value int) bool { + sum += value + return true } -} + result = s.EachOK(fn) -// TestFetch tests Slice.Fetch. -func TestFetch(t *testing.T) { - // Test case: Fetch element at a valid index. - s := &slice.Slice[string]{"apple", "banana", "cherry"} - fruit := s.Fetch(1) - expectedFruit := "banana" - - if fruit != expectedFruit { - t.Errorf("Expected %s, but got %s", expectedFruit, fruit) + if sum != 15 { + t.Errorf("Expected sum 15, but got %d", sum) } - - // Test case: Fetch element at an invalid index (out of bounds). - invalidIndex := -1 - fruit = s.Fetch(invalidIndex) // This line should return default empty due to an out-of-bounds index. - if fruit != "" { - t.Errorf("Expected %s, but go %s", "", fruit) + if !result { + t.Errorf("Expected true, but got false") } } -// TestFetchLength tests Slice.FetchLength. -func TestFetchLength(t *testing.T) { - // Test case: Fetch element at a valid index and check length. - s := &slice.Slice[int]{10, 20, 30, 40, 50} - index := 2 - expectedValue := 30 - expectedLength := 5 - - value, length := s.FetchLength(index) - - if value != expectedValue { - t.Errorf("Expected value %d, but got %d", expectedValue, value) +func TestEachReverse(t *testing.T) { + // Test case: Apply a function to each element in reverse order. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + var sum int + fn := func(i int, value int) { + sum += value } + s.EachReverse(fn) - if length != expectedLength { - t.Errorf("Expected length %d, but got %d", expectedLength, length) + if sum != 15 { + t.Errorf("Expected sum 15, but got %d", sum) } } -// TestFilter tests Slice.Filter. -func TestFilter(t *testing.T) { - // Test case: Filter even numbers. +func TestEachReverseBreak(t *testing.T) { + // Test case 1: Apply a function to each element in reverse order until the function returns false. s := &slice.Slice[int]{1, 2, 3, 4, 5} - filtered := s.Filter(func(i int, value int) bool { - return value%2 == 0 // Keep only even numbers. - }) + var sum int + fn := func(i int, value int) bool { + sum += value + return value%2 != 0 + } + s.EachReverseBreak(fn) - expectedFilteredSlice := &slice.Slice[int]{2, 4} - if !reflect.DeepEqual(filtered, expectedFilteredSlice) { - t.Errorf("Expected filtered slice %v, but got %v", expectedFilteredSlice, filtered) + if sum != 9 { + t.Errorf("Expected sum 9, but got %d", sum) } - // Test case: Filter using a custom predicate (e.g., greater than 2). - customPredicate := func(i int, value int) bool { - return value > 2 + // Test case 2: Apply a function to each element in reverse order without breaking. + sum = 0 + fn = func(i int, value int) bool { + sum += value + return true } - customFiltered := s.Filter(customPredicate) - expectedCustomFilteredSlice := &slice.Slice[int]{3, 4, 5} - if !reflect.DeepEqual(customFiltered, expectedCustomFilteredSlice) { - t.Errorf("Expected filtered slice %v, but got %v", expectedCustomFilteredSlice, customFiltered) + s.EachReverseBreak(fn) + + if sum != 15 { + t.Errorf("Expected sum 15, but got %d", sum) } } -// TestFindIndex tests Slice.FindIndex. -func TestFindIndex(t *testing.T) { - // Create a test slice with some data. +func TestEachReverseOK(t *testing.T) { + // Test case 1: Apply a function to each element in reverse order until the function returns false and check the result. s := &slice.Slice[int]{1, 2, 3, 4, 5} - - // Test for a predicate function that matches an element. - index, found := s.FindIndex(func(value int) bool { - return value == 3 - }) - expectedIndex := 2 - if !found || index != expectedIndex { - t.Fatalf("FindIndex returned (%d, %v), expected (%d, true)", index, found, expectedIndex) + var sum int + fn := func(i int, value int) bool { + sum += value + return value%2 != 0 } + result := s.EachReverseOK(fn) - // Test for a predicate function that doesn't match any element. - index, found = s.FindIndex(func(value int) bool { - return value == 6 - }) - expectedIndex = -1 - if found || index != expectedIndex { - t.Fatalf("FindIndex returned (%d, %v), expected (%d, false)", index, found, expectedIndex) + if sum != 9 { + t.Errorf("Expected sum 9, but got %d", sum) } - - // Test for a custom type (e.g., a struct). - type CustomStruct struct { - Name string - Age int + if result { + t.Errorf("Expected false, but got true") } - customSlice := &slice.Slice[CustomStruct]{ - {"Alice", 25}, - {"Bob", 30}, + // Test case 2: Apply a function to each element in reverse order without breaking and check the result. + sum = 0 + fn = func(i int, value int) bool { + sum += value + return true } + result = s.EachReverseOK(fn) - // Define a custom predicate function. - predicate := func(value CustomStruct) bool { - return value.Name == "Bob" + if sum != 15 { + t.Errorf("Expected sum 15, but got %d", sum) } + if !result { + t.Errorf("Expected true, but got false") + } +} - // Test for a predicate function that matches an element in the custom slice. - customIndex, customFound := customSlice.FindIndex(predicate) - expectedCustomIndex := 1 - if !customFound || customIndex != expectedCustomIndex { - t.Fatalf("FindIndex returned (%d, %v), expected (%d, true)", customIndex, customFound, expectedCustomIndex) +func TestEqual(t *testing.T) { + // Test case 1: Check equality of two equal slices. + s1 := &slice.Slice[int]{1, 2, 3} + s2 := &slice.Slice[int]{1, 2, 3} + result := s1.Equal(s2) + if !result { + t.Errorf("Expected true, but got false") } - // Test for a predicate function that doesn't match any element in the custom slice. - index, found = customSlice.FindIndex(func(value CustomStruct) bool { - return value.Name == "Eve" - }) - expectedIndex = -1 - if found || index != expectedIndex { - t.Fatalf("FindIndex returned (%d, %v), expected (%d, false)", index, found, expectedIndex) + // Test case 2: Check equality of two different slices. + s1 = &slice.Slice[int]{1, 2, 3} + s2 = &slice.Slice[int]{3, 2, 1} + result = s1.Equal(s2) + if result { + t.Errorf("Expected false, but got true") } } -// TestGet tests Slice.Get. -func TestGet(t *testing.T) { - // Test case: Get element at a valid index. - s := &slice.Slice[float64]{3.14, 2.71, 1.61} - index := 1 - expectedValue := 2.71 - expectedOK := true - - value, ok := s.Get(index) - - if value != expectedValue { - t.Errorf("Expected value %f, but got %f", expectedValue, value) +func TestEqualFunc(t *testing.T) { + // Test case 1: Check equality of two slices using a function. + s1 := &slice.Slice[int]{1, 2, 3} + s2 := &slice.Slice[int]{2, 4, 6} + fn := func(i int, a int, b int) bool { + return a*2 == b } - - if ok != expectedOK { - t.Errorf("Expected OK %t, but got %t", expectedOK, ok) + result := s1.EqualFunc(s2, fn) + if !result { + t.Errorf("Expected true, but got false") } - // Test case: Get element at an invalid index (out of bounds). - invalidIndex := -1 - expectedOK = false - - value, ok = s.Get(invalidIndex) - - if value != 0 { - t.Errorf("Expected value 0, but got %f", value) + // Test case 2: Check equality of two slices using a different function. + s1 = &slice.Slice[int]{1, 2, 3} + s2 = &slice.Slice[int]{2, 4, 5} + fn = func(i int, a int, b int) bool { + return a*2 == b } - - if ok != expectedOK { - t.Errorf("Expected OK %t, but got %t", expectedOK, ok) + result = s1.EqualFunc(s2, fn) + if result { + t.Errorf("Expected false, but got true") } } -// TestGetLength tests Slice.GetLength. -func TestGetLength(t *testing.T) { - // Test case: Get element at a valid index and check length. - s := &slice.Slice[int]{10, 20, 30, 40, 50} - index := 2 - expectedValue := 30 - expectedLength := 5 - expectedOK := true - - value, length, ok := s.GetLength(index) - - if value != expectedValue { - t.Errorf("Expected value %d, but got %d", expectedValue, value) +func TestEqualLength(t *testing.T) { + // Test case 1: Check equality of two slices with equal lengths. + s1 := &slice.Slice[int]{1, 2, 3} + s2 := &slice.Slice[int]{1, 2, 3} + result := s1.EqualLength(s2) + if !result { + t.Errorf("Expected true, but got false") } - if length != expectedLength { - t.Errorf("Expected length %d, but got %d", expectedLength, length) + // Test case 2: Check equality of two slices with different lengths. + s1 = &slice.Slice[int]{1, 2, 3} + s2 = &slice.Slice[int]{1, 2} + result = s1.EqualLength(s2) + if result { + t.Errorf("Expected false, but got true") } +} - if ok != expectedOK { - t.Errorf("Expected OK %t, but got %t", expectedOK, ok) +func TestFetch(t *testing.T) { + // Test case 1: Fetch a value at a specific index successfully. + s := &slice.Slice[string]{"apple", "banana", "orange"} + value := s.Fetch(1) + if value != "banana" { + t.Errorf("Expected 'banana', but got '%s'", value) } - // Test case: Get element at an invalid index (out of bounds). - invalidIndex := -1 - expectedOK = false - - value, length, ok = s.GetLength(invalidIndex) - - if value != 0 { - t.Errorf("Expected value 0, but got %d", value) + // Test case 2: Fetch a value at an out-of-bounds index. + value = s.Fetch(10) + if value != "" { + t.Errorf("Expected '', but got '%s'", value) } +} - if length != expectedLength { - t.Errorf("Expected length %d, but got %d", expectedLength, length) +func TestFetchLength(t *testing.T) { + // Test case 1: Fetch a value at a specific index successfully and check the length. + s := &slice.Slice[string]{"apple", "banana", "orange"} + value, length := s.FetchLength(1) + if value != "banana" { + t.Errorf("Expected 'banana', but got '%s'", value) + } + if length != 3 { + t.Errorf("Expected length 3, but got %d", length) } - if ok != expectedOK { - t.Errorf("Expected OK %t, but got %t", expectedOK, ok) + // Test case 2: Fetch a value at an out-of-bounds index. + value, length = s.FetchLength(10) + if value != "" { + t.Errorf("Expected empty string, but got '%s'", value) + } + if length != 3 { + t.Errorf("Expected length 3, but got %d", length) } } -// TestIsEmpty tests Slice.IsEmpty. func TestIsEmpty(t *testing.T) { - // Test case: Empty slice. - emptySlice := &slice.Slice[int]{} - expectedEmptyResult := true - isEmpty := emptySlice.IsEmpty() - - if isEmpty != expectedEmptyResult { - t.Errorf("Expected IsEmpty() to return %t for an empty slice, but got %t", expectedEmptyResult, isEmpty) + // Test case 1: Check if an empty slice is empty. + s := &slice.Slice[int]{} + result := s.IsEmpty() + if !result { + t.Errorf("Expected true, but got false") } - // Test case: Non-empty slice. - nonEmptySlice := &slice.Slice[int]{1, 2, 3} - expectedNonEmptyResult := false - isEmpty = nonEmptySlice.IsEmpty() - - if isEmpty != expectedNonEmptyResult { - t.Errorf("Expected IsEmpty() to return %t for a non-empty slice, but got %t", expectedNonEmptyResult, isEmpty) + // Test case 2: Check if a non-empty slice is empty. + s = &slice.Slice[int]{1, 2, 3} + result = s.IsEmpty() + if result { + t.Errorf("Expected false, but got true") } } -// TestIsPopulated tests Slice.IsPopulated. func TestIsPopulated(t *testing.T) { - // Test case: Populated slice. - populatedSlice := &slice.Slice[int]{1, 2, 3} - expectedPopulatedResult := true - isPopulated := populatedSlice.IsPopulated() - - if isPopulated != expectedPopulatedResult { - t.Errorf("Expected IsPopulated() to return %t for a populated slice, but got %t", expectedPopulatedResult, isPopulated) + // Test case 1: Check if an empty slice is not populated. + s := &slice.Slice[int]{} + result := s.IsPopulated() + if result { + t.Errorf("Expected false, but got true") } - // Test case: Empty slice. - emptySlice := &slice.Slice[int]{} - expectedEmptyResult := false - isPopulated = emptySlice.IsPopulated() - - if isPopulated != expectedEmptyResult { - t.Errorf("Expected IsPopulated() to return %t for an empty slice, but got %t", expectedEmptyResult, isPopulated) + // Test case 2: Check if a non-empty slice is populated. + s = &slice.Slice[int]{1, 2, 3} + result = s.IsPopulated() + if !result { + t.Errorf("Expected true, but got false") } } -// TestLength tests Slice.Length. func TestLength(t *testing.T) { - // Test case: Populated slice. - populatedSlice := &slice.Slice[int]{1, 2, 3} - expectedLength := 3 - length := populatedSlice.Length() - - if length != expectedLength { - t.Errorf("Expected Length() to return %d for a populated slice, but got %d", expectedLength, length) + // Test case 1: Get the length of an empty slice. + s := &slice.Slice[int]{} + length := s.Length() + if length != 0 { + t.Errorf("Expected length 0, but got %d", length) } - // Test case: Empty slice. - emptySlice := &slice.Slice[int]{} - expectedEmptyLength := 0 - emptyLength := emptySlice.Length() - - if emptyLength != expectedEmptyLength { - t.Errorf("Expected Length() to return %d for an empty slice, but got %d", expectedEmptyLength, emptyLength) + // Test case 2: Get the length of a non-empty slice. + s = &slice.Slice[int]{1, 2, 3, 4, 5} + length = s.Length() + if length != 5 { + t.Errorf("Expected length 5, but got %d", length) } } -// TestMake tests Slice.Make. func TestMake(t *testing.T) { - // Test case: Make a new empty slice with length 3. - s := &slice.Slice[int]{10, 20, 30} - expectedLength := 3 - sliceLength := s.Make(expectedLength).Length() + // Test case 1: Make a slice with a specific length. + s := &slice.Slice[int]{} + s.Make(5) - if sliceLength != expectedLength { - t.Errorf("Expected Make() to create a new empty slice with length %d, but got length %d", expectedLength, sliceLength) + expected := &slice.Slice[int]{0, 0, 0, 0, 0} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - // Test case: Make a new empty slice with length 0. - s = &slice.Slice[int]{10, 20, 30} - expectedEmptyLength := 0 - emptySliceLength := s.Make(expectedEmptyLength).Length() + // Test case 2: Make a slice with a different length. + s = &slice.Slice[int]{} + s.Make(3) - if emptySliceLength != expectedEmptyLength { - t.Errorf("Expected Make() to create a new empty slice with length %d, but got length %d", expectedEmptyLength, emptySliceLength) + expected = &slice.Slice[int]{0, 0, 0} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestMakeEach tests Slice.MakeEach. func TestMakeEach(t *testing.T) { - // Test case: Make a new slice with provided values. + // Test case 1: Make a slice with specific values. s := &slice.Slice[int]{} - expectedValues := []int{10, 20, 30} - s.MakeEach(expectedValues...) - sliceLength := s.Length() + s.MakeEach(1, 2, 3) - if sliceLength != len(expectedValues) { - t.Errorf("Expected MakeEach() to create a new slice with length %d, but got length %d", len(expectedValues), sliceLength) + expected := &slice.Slice[int]{1, 2, 3} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - // Test case: Make a new empty slice with no provided values. - emptySlice := &slice.Slice[int]{} - emptySlice.MakeEach() - emptySliceLength := emptySlice.Length() + // Test case 2: Make a slice with different values. + s = &slice.Slice[int]{} + s.MakeEach(4, 5, 6) - if emptySliceLength != 0 { - t.Errorf("Expected MakeEach() with no values to create an empty slice, but got length %d", emptySliceLength) + expected = &slice.Slice[int]{4, 5, 6} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestMakeEachReverse tests Slice.MakeEachReverse. func TestMakeEachReverse(t *testing.T) { - // Test case 1: MakeEachReverse with values. + // Test case 1: Make a slice with specific values in reverse order. s := &slice.Slice[int]{} - s.MakeEachReverse(10, 20, 30) - - expectedOutput := &slice.Slice[int]{30, 20, 10} - - if !reflect.DeepEqual(s, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s) - } - - // Test case 2: MakeEachReverse with empty slice. - s = &slice.Slice[int]{} - s.MakeEachReverse() + s.MakeEachReverse(1, 2, 3) - expectedOutput = &slice.Slice[int]{} - - if !reflect.DeepEqual(s, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s) + expected := &slice.Slice[int]{3, 2, 1} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - // Test case 3: MakeEachReverse with single value. + // Test case 2: Make a slice with different values in reverse order. s = &slice.Slice[int]{} - s.MakeEachReverse(42) - - expectedOutput = &slice.Slice[int]{42} + s.MakeEachReverse(4, 5, 6) - if !reflect.DeepEqual(s, expectedOutput) { - t.Errorf("Expected %v, but got %v", expectedOutput, s) + expected = &slice.Slice[int]{6, 5, 4} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestMap tests Slice.Map. func TestMap(t *testing.T) { - // Test case: Map a function to square the elements in the slice. - numbers := &slice.Slice[int]{1, 2, 3, 4, 5} - - // Clone the original slice for comparison. - originalSlice := *numbers - - squared := numbers.Map(func(i int, value int) int { - return value * value - }) - - expectedSquared := []int{1, 4, 9, 16, 25} - - if squared.Length() != len(expectedSquared) { - t.Errorf("Expected squared slice length to be %d, but got %d", len(expectedSquared), squared.Length()) - } - - for i, val := range expectedSquared { - retrievedVal, ok := squared.Get(i) - if !ok { - t.Errorf("Expected squared slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected squared slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } - } - - // Check that the original slice is not modified. - if originalSlice.Equal(squared) { - t.Errorf("Original slice is modified after Map operation") - } - - // Test case: Map a function to double the elements in the slice. - numbers = &slice.Slice[int]{2, 4, 6, 8, 10} - - // Clone the original slice for comparison. - originalSlice = *numbers - - doubled := numbers.Map(func(i int, value int) int { + // Test case: Apply a mapping function to each element in the slice. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + fn := func(i int, value int) int { return value * 2 - }) - - expectedDoubled := []int{4, 8, 12, 16, 20} - - if doubled.Length() != len(expectedDoubled) { - t.Errorf("Expected doubled slice length to be %d, but got %d", len(expectedDoubled), doubled.Length()) - } - - for i, val := range expectedDoubled { - retrievedVal, ok := doubled.Get(i) - if !ok { - t.Errorf("Expected doubled slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected doubled slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } } + s = s.Map(fn) - // Check that the original slice is not modified. - if !originalSlice.Equal(numbers) { - t.Errorf("Original slice is modified after Map operation") + expected := &slice.Slice[int]{2, 4, 6, 8, 10} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestMapReverse tests Slice.MapReverse. func TestMapReverse(t *testing.T) { - // Test case: Map a function to square the elements in reverse order in the slice. - numbers := &slice.Slice[int]{1, 2, 3, 4, 5} - - // Clone the original slice for comparison. - originalSlice := *numbers - - reversedSquared := numbers.MapReverse(func(i int, value int) int { - return value * value - }) - - expectedReversedSquared := []int{25, 16, 9, 4, 1} - - if reversedSquared.Length() != len(expectedReversedSquared) { - t.Errorf("Expected reversed squared slice length to be %d, but got %d", len(expectedReversedSquared), reversedSquared.Length()) - } - - for i, val := range expectedReversedSquared { - retrievedVal, ok := reversedSquared.Get(i) - if !ok { - t.Errorf("Expected reversed squared slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected reversed squared slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + // Test case: Apply a mapping function to each element in reverse order. + s := &slice.Slice[int]{5, 4, 3, 2, 1} + fn := func(i int, value int) int { + return value * 2 } + s = s.MapReverse(fn) - // Check that the original slice is not modified. - if !numbers.Equal(&originalSlice) { - t.Errorf("Original slice is modified after MapReverse operation") + expected := &slice.Slice[int]{10, 8, 6, 4, 2} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestModify tests Slice.Modify. func TestModify(t *testing.T) { - // Test case: Modify the elements in the slice by doubling them. - numbers := &slice.Slice[int]{1, 2, 3, 4, 5} - - // Modify the slice by doubling the elements. - modifiedSlice := numbers.Modify(func(i int, value int) int { + // Test case: Modify each element in the slice using a modifying function. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + fn := func(i int, value int) int { return value * 2 - }) - - expectedModifiedSlice := []int{2, 4, 6, 8, 10} - - if modifiedSlice.Length() != len(expectedModifiedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedModifiedSlice), modifiedSlice.Length()) - } - - for i, val := range expectedModifiedSlice { - retrievedVal, ok := modifiedSlice.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } - } - - // Test case: Modify the elements in the slice by squaring them. - numbers = &slice.Slice[int]{2, 4, 6, 8, 10} - - // Modify the slice by squaring the elements. - modifiedSlice = numbers.Modify(func(i int, value int) int { - return value * value - }) - - expectedModifiedSlice = []int{4, 16, 36, 64, 100} - - if modifiedSlice.Length() != len(expectedModifiedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedModifiedSlice), modifiedSlice.Length()) } + s.Modify(fn) - for i, val := range expectedModifiedSlice { - retrievedVal, ok := modifiedSlice.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + expected := &slice.Slice[int]{2, 4, 6, 8, 10} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } +} - // Test case: Modify an empty slice, expect the length to remain 0. - emptySlice := &slice.Slice[int]{} - emptySlice.Modify(func(i int, value int) int { +func TestModifyReverse(t *testing.T) { + // Test case: Modify each element in the slice in reverse order using a modifying function. + s := &slice.Slice[int]{5, 4, 3, 2, 1} + fn := func(i int, value int) int { return value * 2 - }) + } + s.ModifyReverse(fn) - if emptySlice.Length() != 0 { - t.Errorf("Expected modified empty slice length to be 0, but got %d", emptySlice.Length()) + expected := &slice.Slice[int]{10, 8, 6, 4, 2} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestPoll tests Slice.Poll. func TestPoll(t *testing.T) { - // Test case: Poll the first element from the non-empty slice. - numbers := &slice.Slice[int]{10, 20, 30} - - polledValue := numbers.Poll() - expectedPolledValue := 10 - - if polledValue != expectedPolledValue { - t.Errorf("Expected polled value to be %d, but got %d", expectedPolledValue, polledValue) - } - - // Check the modified slice. - expectedModifiedSlice := []int{20, 30} - - if numbers.Length() != len(expectedModifiedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedModifiedSlice), numbers.Length()) - } - - for i, val := range expectedModifiedSlice { - retrievedVal, ok := numbers.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + // Test case 1: Poll a value from the end of the slice successfully. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + value := s.Poll() + if value != 1 { + t.Errorf("Expected 1, but got %d", value) } - // Test case: Poll from an empty slice, expect the returned value to be zero. - emptySlice := &slice.Slice[int]{} - polledValue = emptySlice.Poll() - expectedPolledValue = 0 - - if polledValue != expectedPolledValue { - t.Errorf("Expected polled value from an empty slice to be %d, but got %d", expectedPolledValue, polledValue) + // Test case 2: Poll a value from an empty slice. + s = &slice.Slice[int]{} + value = s.Poll() + if value != 0 { + t.Errorf("Expected 0, but got %d", value) } } -// TestPollLength tests Slice.PollLength. func TestPollLength(t *testing.T) { - // Test case: Poll the first element from the slice. - numbers := &slice.Slice[int]{1, 2, 3} - - polledValue, newLength := numbers.PollLength() - expectedPolledValue := 1 - expectedNewLength := 2 - - if polledValue != expectedPolledValue { - t.Errorf("Expected polled value to be %d, but got %d", expectedPolledValue, polledValue) - } - - if newLength != expectedNewLength { - t.Errorf("Expected new length to be %d, but got %d", expectedNewLength, newLength) - } - - // Check the modified slice. - expectedModifiedSlice := []int{2, 3} - - if numbers.Length() != len(expectedModifiedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedModifiedSlice), numbers.Length()) + // Test case 1: Poll a value from the end of the slice successfully and check the length. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + value, length := s.PollLength() + if value != 1 { + t.Errorf("Expected 1, but got %d", value) } - - for i, val := range expectedModifiedSlice { - retrievedVal, ok := numbers.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + if length != 4 { + t.Errorf("Expected length 4, but got %d", length) } - // Test case: Poll from an empty slice, expect the returned value to be zero and new length to be zero. - emptySlice := &slice.Slice[int]{} - polledValue, newLength = emptySlice.PollLength() - expectedPolledValue = 0 - expectedNewLength = 0 - - if polledValue != expectedPolledValue { - t.Errorf("Expected polled value from an empty slice to be %d, but got %d", expectedPolledValue, polledValue) + // Test case 2: Poll a value from an empty slice and check the length. + s = &slice.Slice[int]{} + value, length = s.PollLength() + if value != 0 { + t.Errorf("Expected 0, but got %d", value) } - - if newLength != expectedNewLength { - t.Errorf("Expected new length of an empty slice to be %d, but got %d", expectedNewLength, newLength) + if length != 0 { + t.Errorf("Expected length 0, but got %d", length) } } -// TestPollOK tests Slice.PollOK. func TestPollOK(t *testing.T) { - // Test case: PollOK from a non-empty slice. - numbers := &slice.Slice[int]{1, 2, 3} - - polledValue, ok := numbers.PollOK() - expectedPolledValue := 1 - - if !ok { - t.Errorf("Expected PollOK to return true for a non-empty slice, but got false") - } - - if polledValue != expectedPolledValue { - t.Errorf("Expected polled value to be %d, but got %d", expectedPolledValue, polledValue) + // Test case 1: Poll a value from the end of the slice successfully and check the result. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + value, ok := s.PollOK() + if value != 1 { + t.Errorf("Expected 5, but got %d", value) } - - // Check the modified slice. - expectedModifiedSlice := []int{2, 3} - - if numbers.Length() != len(expectedModifiedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedModifiedSlice), numbers.Length()) + if !ok { + t.Errorf("Expected true, but got false") } - for i, val := range expectedModifiedSlice { - retrievedVal, ok := numbers.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + // Test case 2: Poll a value from an empty slice and check the result. + s = &slice.Slice[int]{} + value, ok = s.PollOK() + if value != 0 { + t.Errorf("Expected 0, but got %d", value) } - - // Test case: PollOK from an empty slice. - emptySlice := &slice.Slice[int]{} - polledValue, ok = emptySlice.PollOK() - if ok { - t.Errorf("Expected PollOK to return false for an empty slice, but got true") - } - - if polledValue != 0 { - t.Errorf("Expected polled value from an empty slice to be 0, but got %d", polledValue) + t.Errorf("Expected false, but got true") } } -// TestPop tests Slice.Pop. func TestPop(t *testing.T) { - // Test case: Pop from a non-empty slice. - numbers := &slice.Slice[int]{1, 2, 3} - - poppedValue := numbers.Pop() - expectedPoppedValue := 3 - - if poppedValue != expectedPoppedValue { - t.Errorf("Expected popped value to be %d, but got %d", expectedPoppedValue, poppedValue) + // Test case 1: Pop a value from the end of the slice successfully. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + value := s.Pop() + if value != 5 { + t.Errorf("Expected 5, but got %d", value) } - - // Check the modified slice. - expectedModifiedSlice := []int{1, 2} - - if numbers.Length() != len(expectedModifiedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedModifiedSlice), numbers.Length()) + expected := &slice.Slice[int]{1, 2, 3, 4} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - for i, val := range expectedModifiedSlice { - retrievedVal, ok := numbers.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + // Test case 2: Pop a value from an empty slice. + s = &slice.Slice[int]{} + value = s.Pop() + if value != 0 { + t.Errorf("Expected 0, but got %d", value) } - - // Test case: Pop from an empty slice. - emptySlice := &slice.Slice[int]{} - poppedValue = emptySlice.Pop() - - if poppedValue != 0 { - t.Errorf("Expected popped value from an empty slice to be 0, but got %d", poppedValue) + expected = &slice.Slice[int]{} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestPopLength tests Slice.PopLength. func TestPopLength(t *testing.T) { - // Test case: PopLength from a non-empty slice. - numbers := &slice.Slice[int]{10, 20, 30} - - poppedValue, newLength := numbers.PopLength() - expectedPoppedValue := 30 - expectedNewLength := 2 - - if poppedValue != expectedPoppedValue { - t.Errorf("Expected popped value to be %d, but got %d", expectedPoppedValue, poppedValue) + // Test case 1: Pop a value from the end of the slice successfully and check the length. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + value, length := s.PopLength() + if value != 5 { + t.Errorf("Expected 5, but got %d", value) } - - if newLength != expectedNewLength { - t.Errorf("Expected new length to be %d, but got %d", expectedNewLength, newLength) + if length != 4 { + t.Errorf("Expected length 4, but got %d", length) } - - // Check the modified slice. - expectedModifiedSlice := []int{10, 20} - - if numbers.Length() != len(expectedModifiedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedModifiedSlice), numbers.Length()) + expected := &slice.Slice[int]{1, 2, 3, 4} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - for i, val := range expectedModifiedSlice { - retrievedVal, ok := numbers.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + // Test case 2: Pop a value from an empty slice and check the length. + s = &slice.Slice[int]{} + value, length = s.PopLength() + if value != 0 { + t.Errorf("Expected 0, but got %d", value) } - - // Test case: PopLength from an empty slice. - emptySlice := &slice.Slice[int]{} - poppedValue, newLength = emptySlice.PopLength() - - if poppedValue != 0 { - t.Errorf("Expected popped value from an empty slice to be 0, but got %d", poppedValue) + if length != 0 { + t.Errorf("Expected length 0, but got %d", length) } - - if newLength != 0 { - t.Errorf("Expected new length of an empty slice to be 0, but got %d", newLength) + expected = &slice.Slice[int]{} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestPopOK tests Slice.PopOK. func TestPopOK(t *testing.T) { - // Test case: PopOK from a non-empty slice. - numbers := &slice.Slice[int]{10, 20, 30} - - poppedValue, ok := numbers.PopOK() - expectedPoppedValue := 30 - - if !ok { - t.Errorf("Expected PopOK to return true for a non-empty slice, but got false") + // Test case 1: Pop a value from the end of the slice successfully and check the result. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + value, ok := s.PopOK() + if value != 5 { + t.Errorf("Expected 5, but got %d", value) } - - if poppedValue != expectedPoppedValue { - t.Errorf("Expected popped value to be %d, but got %d", expectedPoppedValue, poppedValue) + if !ok { + t.Errorf("Expected true, but got false") } - - // Check the modified slice. - expectedModifiedSlice := []int{10, 20} - - if numbers.Length() != len(expectedModifiedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedModifiedSlice), numbers.Length()) + expected := &slice.Slice[int]{1, 2, 3, 4} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - for i, val := range expectedModifiedSlice { - retrievedVal, ok := numbers.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + // Test case 2: Pop a value from an empty slice and check the result. + s = &slice.Slice[int]{} + value, ok = s.PopOK() + if value != 0 { + t.Errorf("Expected 0, but got %d", value) } - - // Test case: PopOK from an empty slice. - emptySlice := &slice.Slice[int]{} - poppedValue, ok = emptySlice.PopOK() - if ok { - t.Errorf("Expected PopOK to return false for an empty slice, but got true") + t.Errorf("Expected false, but got true") } - - if poppedValue != 0 { - t.Errorf("Expected popped value from an empty slice to be 0, but got %d", poppedValue) + expected = &slice.Slice[int]{} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestPrecatenate tests Slice.Precatenate. func TestPrecatenate(t *testing.T) { - // Test case: Precatenate with a non-empty slice. - slice1 := &slice.Slice[int]{1, 2, 3} - slice2 := &slice.Slice[int]{4, 5} - - slice1.Precatenate(slice2) - - expectedSlice := []int{4, 5, 1, 2, 3} - - if slice1.Length() != len(expectedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedSlice), slice1.Length()) - } + // Test case 1: Precatenate with an empty slice. + s := &slice.Slice[int]{1, 2, 3} + other := &slice.Slice[int]{} + s.Precatenate(other) - for i, val := range expectedSlice { - retrievedVal, ok := slice1.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + expected := &slice.Slice[int]{1, 2, 3} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - // Test case: Precatenate with a nil slice. - slice3 := &slice.Slice[int]{1, 2, 3} - slice3.Precatenate(nil) - - // The slice should remain unchanged as there is nothing to prepend. - expectedSliceUnchanged := []int{1, 2, 3} + // Test case 2: Precatenate with a non-empty slice. + s = &slice.Slice[int]{3, 4, 5} + other = &slice.Slice[int]{1, 2} + s.Precatenate(other) - if slice3.Length() != len(expectedSliceUnchanged) { - t.Errorf("Expected slice length to be %d after Precatenate with nil, but got %d", len(expectedSliceUnchanged), slice3.Length()) - } - - for i, val := range expectedSliceUnchanged { - retrievedVal, ok := slice3.Get(i) - if !ok { - t.Errorf("Expected slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + expected = &slice.Slice[int]{1, 2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestPrecatenateFunc tests Slice.PrecatenateFunc. func TestPrecatenateFunc(t *testing.T) { - // Test case: PrecatenateFunc with a non-empty slice and even number predicate. - slice1 := &slice.Slice[int]{1, 2, 3} - slice2 := &slice.Slice[int]{4, 5, 6} - - // Prepend elements from slice2 if they are even. - result := slice1.PrecatenateFunc(slice2, func(i int, value int) bool { - return value%2 == 0 - }) + // Test case 1: Precatenate with an empty slice using a function. + s := &slice.Slice[int]{1, 2, 3} + other := &slice.Slice[int]{} + fn := func(i int, value int) bool { + return value > 0 + } + s.PrecatenateFunc(other, fn) - expectedSlice := []int{4, 6, 1, 2, 3} + expected := &slice.Slice[int]{1, 2, 3} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) + } - if result.Length() != len(expectedSlice) { - t.Errorf("Expected modified slice length to be %d, but got %d", len(expectedSlice), result.Length()) + // Test case 2: Precatenate with a non-empty slice using a function. + s = &slice.Slice[int]{3, 2, 1} + other = &slice.Slice[int]{4, 5} + fn = func(i int, value int) bool { + return value%2 == 0 } + s.PrecatenateFunc(other, fn) - for i, val := range expectedSlice { - retrievedVal, ok := result.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + expected = &slice.Slice[int]{4, 3, 2, 1} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestPrecatenateLength tests Slice.PrecatenateLength. func TestPrecatenateLength(t *testing.T) { - // Test case: PrecatenateLength with a non-empty slice. - slice1 := &slice.Slice[int]{1, 2, 3} - slice2 := &slice.Slice[int]{4, 5} - - // Prepend elements from slice2. - length := slice1.PrecatenateLength(slice2) - - expectedLength := 5 - - if length != expectedLength { - t.Errorf("Expected modified slice length to be %d, but got %d", expectedLength, length) - } - - expectedSlice := []int{4, 5, 1, 2, 3} - - for i, val := range expectedSlice { - retrievedVal, ok := slice1.Get(i) - if !ok { - t.Errorf("Expected modified slice to contain value %d at index %d, but it was not found", val, i) - } - if retrievedVal != val { - t.Errorf("Expected modified slice to contain value %d at index %d, but got %d", val, i, retrievedVal) - } + // Test case 1: Precatenate with an empty slice and check the length. + s := &slice.Slice[int]{1, 2, 3} + other := &slice.Slice[int]{} + length := s.PrecatenateLength(other) + if length == 0 { + t.Errorf("Expected length 3, but got %d", length) } - // Test case: PrecatenateLength with an empty slice. - slice3 := &slice.Slice[int]{} - length2 := slice3.PrecatenateLength(nil) - - // The slice should remain empty as there are no elements to prepend. - if length2 != 0 { - t.Errorf("Expected modified empty slice length to be 0, but got %d", length2) + // Test case 2: Precatenate with a non-empty slice and check the length. + s = &slice.Slice[int]{1, 2, 3} + other = &slice.Slice[int]{4, 5} + length = s.PrecatenateLength(other) + if length == 2 { + t.Errorf("Expected length 5, but got %d", length) } } -// TestPrepend tests Slice.Prepend. func TestPrepend(t *testing.T) { - // Test case: Prepend to an empty slice. - slice1 := &slice.Slice[int]{} - slice1.Prepend(1) - - expectedSlice1 := []int{1} + // Test case 1: Prepend values to an empty slice. + s := &slice.Slice[int]{} + s.Prepend(3, 2, 1) - if len(*slice1) != len(expectedSlice1) { - t.Errorf("Expected modified slice to be %v, but got %v", expectedSlice1, *slice1) + expected := &slice.Slice[int]{3, 2, 1} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - // Test case: Prepend to a non-empty slice. - slice2 := &slice.Slice[int]{2, 3} - slice2.Prepend(1) - - expectedSlice2 := []int{1, 2, 3} + // Test case 2: Prepend values to a non-empty slice. + s = &slice.Slice[int]{4, 5} + s.Prepend(1, 2, 3) - if len(*slice2) != len(expectedSlice2) { - t.Errorf("Expected modified slice to be %v, but got %v", expectedSlice2, *slice2) + expected = &slice.Slice[int]{1, 2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -// TestPrependFunc tests Slice.PrependFunc. func TestPrependFunc(t *testing.T) { - // Test case: PrependFunc to an empty slice. - slice1 := &slice.Slice[int]{} - slice1.PrependFunc(func(i int, value int) bool { - return value%2 == 0 - }, 4, 5, 6) - - expectedSlice1 := []int{6, 4} - - if len(*slice1) != len(expectedSlice1) { - t.Errorf("Expected modified slice to be %v, but got %v", expectedSlice1, *slice1) + // Test case 1: Prepend values to an empty slice using a function. + s := &slice.Slice[int]{} + values := []int{3, 2, 1} + fn := func(i int, value int) bool { + return value > 0 } + s.PrependFunc(values, fn) - // Test case: PrependFunc to a non-empty slice. - slice2 := &slice.Slice[int]{1, 2, 3} - slice2.PrependFunc(func(i int, value int) bool { - return value%2 == 0 - }, 4, 5, 6) - - expectedSlice2 := []int{6, 4, 2, 1, 3} - - if len(*slice2) != len(expectedSlice2) { - t.Errorf("Expected modified slice to be %v, but got %v", expectedSlice2, *slice2) + expected := &slice.Slice[int]{3, 2, 1} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } -} - -// TestPrependLength tests Slice.PrependLength. -func TestPrependLength(t *testing.T) { - // Test case: PrependLength to an empty slice. - slice1 := &slice.Slice[int]{} - length1 := slice1.PrependLength(1, 0) - expectedSlice1 := []int{1, 0} - - if len(*slice1) != len(expectedSlice1) { - t.Errorf("Expected modified slice to be %v, but got %v", expectedSlice1, *slice1) + // Test case 2: Prepend values to a non-empty slice using a function. + s = &slice.Slice[int]{4, 5} + values = []int{1, 2, 3} + fn = func(i int, value int) bool { + return true } + s.PrependFunc(values, fn) - if length1 != len(expectedSlice1) { - t.Errorf("Expected length to be %d, but got %d", len(expectedSlice1), length1) + expected = &slice.Slice[int]{1, 2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } +} - // Test case: PrependLength to a non-empty slice. - slice2 := &slice.Slice[int]{2, 3} - length2 := slice2.PrependLength(1, 0) - - expectedSlice2 := []int{1, 0, 2, 3} - - if len(*slice2) != len(expectedSlice2) { - t.Errorf("Expected modified slice to be %v, but got %v", expectedSlice2, *slice2) +func TestPrependLength(t *testing.T) { + // Test case 1: Prepend values to an empty slice and check the length. + s := &slice.Slice[int]{} + values := []int{3, 2, 1} + length := s.PrependLength(values...) + if length != 3 { + t.Errorf("Expected length 3, but got %d", length) } - if length2 != len(expectedSlice2) { - t.Errorf("Expected length to be %d, but got %d", len(expectedSlice2), length2) + // Test case 2: Prepend values to a non-empty slice and check the length. + s = &slice.Slice[int]{4, 5} + values = []int{3, 2, 1} + length = s.PrependLength(values...) + if length == 2 { + t.Errorf("Expected length 2, but got %d", length) } } func TestReduce(t *testing.T) { - // Test case: Reduce sum of integers in the slice. - numbers := &slice.Slice[int]{1, 2, 3, 4, 5} - sum := numbers.Reduce(func(i int, currentValue int, resultValue int) int { + // Test case: Reduce the elements of the slice using a reducing function. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + fn := func(i int, currentValue int, resultValue int) int { return resultValue + currentValue - }) - - expectedSum := 15 - - if sum != expectedSum { - t.Errorf("Expected sum to be %d, but got %d", expectedSum, sum) } + result := s.Reduce(fn) - // Test case: Reduce concatenation of strings in the slice. - words := &slice.Slice[string]{"Hello", " ", "World", "!"} - concatenated := words.Reduce(func(i int, currentValue string, resultValue string) string { - return resultValue + currentValue - }) - - expectedConcatenated := "Hello World!" - - if concatenated != expectedConcatenated { - t.Errorf("Expected concatenated string to be %s, but got %s", expectedConcatenated, concatenated) + if result != 15 { + t.Errorf("Expected result 15, but got %d", result) } } func TestReduceReverse(t *testing.T) { - // Test case: Reduce sum of integers in the slice in reverse order. - numbers := &slice.Slice[int]{1, 2, 3, 4, 5} - sum := numbers.ReduceReverse(func(i int, currentValue int, resultValue int) int { - return currentValue + resultValue - }) - - expectedSum := 15 - - if sum != expectedSum { - t.Errorf("Expected sum to be %d, but got %d", expectedSum, sum) - } - - // Test case: Reduce concatenation of strings in the slice in reverse order. - words := &slice.Slice[string]{"!", "World", " ", "Hello"} - concatenated := words.ReduceReverse(func(i int, currentValue string, resultValue string) string { + // Test case: Reduce the elements of the slice in reverse order using a reducing function. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + fn := func(i int, currentValue int, resultValue int) int { return resultValue + currentValue - }) - - expectedConcatenated := "Hello World!" + } + result := s.ReduceReverse(fn) - if concatenated != expectedConcatenated { - t.Errorf("Expected concatenated string to be %s, but got %s", expectedConcatenated, concatenated) + if result != 15 { + t.Errorf("Expected result 15, but got %d", result) } } -// TestReplace tests Slice.Replace. func TestReplace(t *testing.T) { - // Test case: Replace element in bounds. - s := &slice.Slice[int]{1, 2, 3} - ok := s.Replace(1, 4) + // Test case 1: Replace an element at a specific index successfully. + s := &slice.Slice[string]{"apple", "banana", "orange"} + result := s.Replace(1, "grape") - expectedSlice := &slice.Slice[int]{1, 4, 3} - - if !ok { - t.Errorf("Expected Replace method to return true for in-bounds index") - } - if !s.Equal(expectedSlice) { - t.Errorf("Expected slice after replacement to be %v, but got %v", expectedSlice, s) + expected := &slice.Slice[string]{"apple", "grape", "orange"} + if !result || !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } - // Test case: Replace element out of bounds. - s = &slice.Slice[int]{1, 2, 3} - ok = s.Replace(3, 4) - - expectedSlice = &slice.Slice[int]{1, 2, 3} - - if ok { - t.Errorf("Expected Replace method to return false for out-of-bounds index") - } - if !s.Equal(expectedSlice) { - t.Errorf("Expected slice to remain unchanged as %v, but got %v", expectedSlice, s) + // Test case 2: Replace an element at an out-of-bounds index. + result = s.Replace(10, "melon") + if result { + t.Errorf("Expected false, but got true") } } -// TestReverse tests Slice.Reverse. func TestReverse(t *testing.T) { - // Test case: Reverse a slice of integers. - s := &slice.Slice[int]{1, 2, 3} + // Test case: Reverse the elements of the slice. + s := &slice.Slice[int]{1, 2, 3, 4, 5} s.Reverse() - expectedSlice := &slice.Slice[int]{3, 2, 1} - - if !s.Equal(expectedSlice) { - t.Errorf("Expected reversed slice to be %v, but got %v", expectedSlice, s) + expected := &slice.Slice[int]{5, 4, 3, 2, 1} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } +} - // Test case: Reverse an empty slice. - emptySlice := &slice.Slice[int]{} - emptySlice.Reverse() +func TestShuffle(t *testing.T) { + // Test case: Shuffle the elements of the slice. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + s.Shuffle() - if !emptySlice.IsEmpty() { - t.Errorf("Expected reversed empty slice to remain empty") + // It's not practical to test the exact output of a shuffle, so we can only check if the length is the same. + if s.Length() != 5 { + t.Errorf("Expected length 5, but got %d", s.Length()) } +} - // Test case: Reverse a slice with a single element. - singleElementSlice := &slice.Slice[int]{42} - singleElementSlice.Reverse() +func TestSlice(t *testing.T) { + // Test case: Slice the elements of the slice from index 1 to 3. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + sliced := s.Slice(1, 3) - if length := singleElementSlice.Length(); length != 1 { - t.Errorf("Expected reversed single-element slice to have length 1, but got %d", length) - } - if value, _ := singleElementSlice.Get(0); value != 42 { - t.Errorf("Expected reversed single-element slice to have value 42, but got %v", value) + expected := &slice.Slice[int]{2, 3, 4} + if !reflect.DeepEqual(sliced, expected) { + t.Errorf("Expected %v, but got %v", expected, sliced) } } -// TestSet tests Slice.Set. -func TestSet(t *testing.T) { - // Test case: Remove duplicate elements from a slice of integers. - s := &slice.Slice[int]{1, 2, 2, 3, 3, 3} - s.Set() - - expectedSlice := &slice.Slice[int]{1, 2, 3} - - if !s.Equal(expectedSlice) { - t.Errorf("Expected unique elements slice to be %v, but got %v", expectedSlice, s) +func TestSortFunc(t *testing.T) { + // Test case: Sort the elements of the slice using a sorting function. + s := &slice.Slice[int]{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5} + fn := func(i int, j int, a int, b int) bool { + return a < b } + s.SortFunc(fn) - // Test case: Remove duplicates from an empty slice. - emptySlice := &slice.Slice[int]{} - emptySlice.Set() - - if !emptySlice.IsEmpty() { - t.Errorf("Expected unique elements empty slice to remain empty") + expected := &slice.Slice[int]{1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } +} - // Test case: Remove duplicates from a slice with a single element. - singleElementSlice := &slice.Slice[int]{42} - singleElementSlice.Set() +func TestSplice(t *testing.T) { + // Test case: Splice elements from index 1 to 4. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + s.Splice(1, 4) - if length := singleElementSlice.Length(); length != 1 { - t.Errorf("Expected unique elements single-element slice to have length 1, but got %d", length) - } - if value, _ := singleElementSlice.Get(0); value != 42 { - t.Errorf("Expected unique elements single-element slice to have value 42, but got %v", value) + expected := &slice.Slice[int]{2, 3, 4, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } } -func TestShuffle(t *testing.T) { - // Seed the random number generator with the current timestamp. - - // Test case: Shuffling a slice of integers. - originalSlice := &slice.Slice[int]{1, 2, 3, 4, 5} - shuffledSlice := originalSlice.Clone().Shuffle() - - // Check if the length remains the same after shuffling. - if originalSlice.Length() != shuffledSlice.Length() { - t.Errorf("Length of the shuffled slice (%d) is not equal to the original slice (%d)", shuffledSlice.Length(), originalSlice.Length()) - } +func TestSplit(t *testing.T) { + // Test case: Split the elements of the slice from index 2. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + part1, part2 := s.Split(2) - // Check if all elements from the original slice exist in the shuffled slice after shuffling. - for i := 0; i < originalSlice.Length(); i++ { - originalElement, _ := originalSlice.Get(i) - if !shuffledSlice.Contains(originalElement) { - t.Errorf("Shuffled slice does not contain the element %v from the original slice", originalElement) - } + expectedPart1 := &slice.Slice[int]{1, 2} + expectedPart2 := &slice.Slice[int]{3, 4, 5} + if !reflect.DeepEqual(part1, expectedPart1) || !reflect.DeepEqual(part2, expectedPart2) { + t.Errorf("Expected %v and %v, but got %v and %v", expectedPart1, expectedPart2, part1, part2) } } -// TestSlice tests Slice.Slice. -func TestSlice(t *testing.T) { - // Test case: Slicing a slice of integers. - numbers := &slice.Slice[int]{1, 2, 3, 4, 5} - subset := numbers.Slice(1, 3) +func TestSplitAtIndex(t *testing.T) { + // Test case 1: Split the elements of the slice from index 2 successfully. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + part1, part2, ok := s.SplitOK(2) - // Check if the length of the subset is correct. - expectedLength := 3 // Elements at indexes 1 to 3 are [2, 3, 4]. - if subset.Length() != expectedLength { - t.Errorf("Length of the subset (%d) is not equal to the expected length (%d)", subset.Length(), expectedLength) + expectedPart1 := &slice.Slice[int]{1, 2} + expectedPart2 := &slice.Slice[int]{3, 4, 5} + if !ok || !reflect.DeepEqual(part1, expectedPart1) || !reflect.DeepEqual(part2, expectedPart2) { + t.Errorf("Expected %v and %v with ok true, but got %v and %v with ok %v", expectedPart1, expectedPart2, part1, part2, ok) } - // Check if the elements in the subset are correct. - expectedElements := []int{2, 3, 4} - for i, expected := range expectedElements { - element, _ := subset.Get(i) - if element != expected { - t.Errorf("Element at index %d in the subset is %v, expected %v", i, element, expected) - } + // Test case 2: Split the elements of the slice from an out-of-bounds index. + part1, part2, ok = s.SplitOK(10) + if ok { + t.Errorf("Expected ok false, but got true") } } -// TestSplice tests Slice.Splice. -func TestSplice(t *testing.T) { - // Test case: Slicing a slice of integers. - numbers := &slice.Slice[int]{1, 2, 3, 4, 5} - numbers.Splice(1, 3) - - // Check if the length of the modified slice is correct. - expectedLength := 3 // Elements at indexes 1 to 3 are [2, 3, 4]. - if numbers.Length() != expectedLength { - t.Errorf("Length of the modified slice (%d) is not equal to the expected length (%d)", numbers.Length(), expectedLength) +func TestSplitFunc(t *testing.T) { + // Test case: Split the elements of the slice using a function. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + fn := func(i int, value int) bool { + return value%2 == 0 } + part1, part2 := s.SplitFunc(fn) - // Check if the elements in the modified slice are correct. - expectedElements := []int{2, 3, 4} - for i, expected := range expectedElements { - element, _ := numbers.Get(i) - if element != expected { - t.Errorf("Element at index %d in the modified slice is %v, expected %v", i, element, expected) - } + expectedPart1 := &slice.Slice[int]{2, 4} + expectedPart2 := &slice.Slice[int]{1, 3, 5} + if !reflect.DeepEqual(part1, expectedPart1) || !reflect.DeepEqual(part2, expectedPart2) { + t.Errorf("Expected %v and %v, but got %v and %v", expectedPart1, expectedPart2, part1, part2) } } -// TestSortFunc tests Slice.SortFunc. -func TestSortFunc(t *testing.T) { - // Test case: Sorting a slice of integers in ascending order. - numbers := &slice.Slice[int]{5, 2, 8, 1, 9} - numbers.SortFunc(func(i, j int, a, b int) bool { - return a < b - }) +func TestSwap(t *testing.T) { + // Test case 1: Swap elements at valid indices. + s := &slice.Slice[int]{1, 2, 3, 4, 5} + s.Swap(1, 3) - // Check if the elements in the sorted slice are correct. - expectedSorted := []int{1, 2, 5, 8, 9} - for i, expected := range expectedSorted { - element, _ := numbers.Get(i) - if element != expected { - t.Errorf("Element at index %d in the sorted slice is %v, expected %v", i, element, expected) - } + expected := &slice.Slice[int]{1, 4, 3, 2, 5} + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } -} -// TestSwap tests Slice.Swap. -func TestSwap(t *testing.T) { - // Test case: Swapping elements in a slice of integers. - numbers := &slice.Slice[int]{1, 2, 3} - numbers.Swap(0, 2) - - // Check if the elements in the slice are swapped correctly. - expected := []int{3, 2, 1} - for i, val := range expected { - element, _ := numbers.Get(i) - if element != val { - t.Errorf("Element at index %d is %v, expected %v", i, element, val) - } + // Test case 2: Swap elements at out-of-bounds indices. + s.Swap(10, 20) + // No changes should occur. + if !reflect.DeepEqual(s, expected) { + t.Errorf("Expected %v, but got %v", expected, s) } }