fn: Added new slice functions.

Signed-off-by: Ononiwu Maureen <59079323+Chinwendu20@users.noreply.github.com>
This commit is contained in:
Ononiwu Maureen 2024-05-05 21:05:59 +01:00
parent f88f120e91
commit 30c9b86d62
No known key found for this signature in database
GPG Key ID: 82470E85193AD2DA
2 changed files with 135 additions and 0 deletions

View File

@ -1,5 +1,13 @@
package fn
import "golang.org/x/exp/constraints"
// Number is a type constraint for all numeric types in Go (integers,
// float and complex numbers)
type Number interface {
constraints.Integer | constraints.Float | constraints.Complex
}
// All returns true when the supplied predicate evaluates to true for all of
// the values in the slice.
func All[A any](pred func(A) bool, s []A) bool {
@ -168,3 +176,25 @@ func ZipWith[A, B, C any](f func(A, B) C, a []A, b []B) []C {
return res
}
// SliceToMap converts a slice to a map using the provided key and value
// functions.
func SliceToMap[A any, K comparable, V any](s []A, keyFunc func(A) K,
valueFunc func(A) V) map[K]V {
res := make(map[K]V, len(s))
for _, val := range s {
key := keyFunc(val)
value := valueFunc(val)
res[key] = value
}
return res
}
// Sum calculates the sum of a slice of numbers, `items`.
func Sum[B Number](items []B) B {
return Foldl(func(a, b B) B {
return a + b
}, 0, items)
}

View File

@ -1,6 +1,7 @@
package fn
import (
"fmt"
"slices"
"testing"
@ -136,3 +137,107 @@ func TestZipWith(t *testing.T) {
z, []bool{false, true, false, false, false},
))
}
// TestSum checks if the Sum function correctly calculates the sum of the
// numbers in the slice.
func TestSum(t *testing.T) {
tests := []struct {
name string
items interface{}
result interface{}
}{
{
name: "Sum of positive integers",
items: []int{1, 2, 3},
result: 6,
},
{
name: "Sum of negative integers",
items: []int{-1, -2, -3},
result: -6,
},
{
name: "Sum of float numbers",
items: []float64{1.1, 2.2, 3.3},
result: 6.6,
},
{
name: "Sum of complex numbers",
items: []complex128{
complex(1, 1),
complex(2, 2),
complex(3, 3),
},
result: complex(6, 6),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch v := tt.items.(type) {
case []int:
require.Equal(t, tt.result, Sum(v))
case []float64:
require.Equal(t, tt.result, Sum(v))
case []complex128:
require.Equal(t, tt.result, Sum(v))
}
})
}
}
// TestSliceToMap tests the SliceToMap function.
func TestSliceToMap(t *testing.T) {
tests := []struct {
name string
slice []int
keyFunc func(int) int
valueFunc func(int) string
expected map[int]string
}{
{
name: "Integers to string map",
slice: []int{1, 2, 3},
keyFunc: func(a int) int { return a },
valueFunc: func(a int) string {
return fmt.Sprintf("Value%d", a)
},
expected: map[int]string{
1: "Value1",
2: "Value2",
3: "Value3",
},
},
{
name: "Duplicates in slice",
slice: []int{1, 2, 2, 3},
keyFunc: func(a int) int { return a },
valueFunc: func(a int) string {
return fmt.Sprintf("Value%d", a)
},
expected: map[int]string{
1: "Value1",
2: "Value2",
3: "Value3",
},
},
{
name: "Empty slice",
slice: []int{},
keyFunc: func(a int) int { return a },
valueFunc: func(a int) string {
return fmt.Sprintf("Value%d", a)
},
expected: map[int]string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(
t, tt.expected,
SliceToMap(tt.slice, tt.keyFunc, tt.valueFunc),
)
})
}
}