feat(pkg): add maps-related functions

This commit is contained in:
Piotr Icikowski 2023-11-03 21:18:22 +01:00
parent 124070116f
commit 8b141b47e8
Signed by: Piotr Icikowski
GPG Key ID: 3931CA47A91F7666
2 changed files with 218 additions and 0 deletions

56
maps.go Normal file
View File

@ -0,0 +1,56 @@
package generics
// Pair represents key-value pair
type Pair[K comparable, V any] struct {
Key K
Value V
}
// MapPairs returns list of map's key-value pairs
func MapPairs[K comparable, V any](src map[K]V) []Pair[K, V] {
dst := make([]Pair[K, V], len(src))
idx := 0
for k, v := range src {
dst[idx] = Pair[K, V]{
Key: k,
Value: v,
}
idx++
}
return dst
}
// MapKeys returns list of map's keys
func MapKeys[K comparable, V any](src map[K]V) []K {
dst := make([]K, len(src))
idx := 0
for k := range src {
dst[idx] = k
idx++
}
return dst
}
// MapValues returns list of map's values
func MapValues[K comparable, V any](src map[K]V) []V {
dst := make([]V, len(src))
idx := 0
for _, v := range src {
dst[idx] = v
idx++
}
return dst
}
// InvertMap returns map with keys and values swapped
func InvertMap[K, V comparable](src map[K]V) map[V]K {
if src == nil {
return nil
}
dst := make(map[V]K, len(src))
for k, v := range src {
dst[v] = k
}
return dst
}

162
maps_test.go Normal file
View File

@ -0,0 +1,162 @@
package generics
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestMapPairs(t *testing.T) {
tests := map[string]struct {
src map[string]int
dst []Pair[string, int]
}{
"nil map": {
src: nil,
dst: []Pair[string, int]{},
},
"empty map": {
src: map[string]int{},
dst: []Pair[string, int]{},
},
"filled map": {
src: map[string]int{
"foo": 1,
"bar": 2,
"baz": 3,
},
dst: []Pair[string, int]{
{
Key: "foo",
Value: 1,
},
{
Key: "bar",
Value: 2,
},
{
Key: "baz",
Value: 3,
},
},
},
}
for name, tc := range tests {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
dst := MapPairs(tc.src)
require.ElementsMatch(t, tc.dst, dst)
})
}
}
func TestMapKeys(t *testing.T) {
tests := map[string]struct {
src map[string]int
dst []string
}{
"nil map": {
src: nil,
dst: []string{},
},
"empty map": {
src: map[string]int{},
dst: []string{},
},
"filled map": {
src: map[string]int{
"foo": 1,
"bar": 2,
"baz": 3,
},
dst: []string{
"foo",
"bar",
"baz",
},
},
}
for name, tc := range tests {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
dst := MapKeys(tc.src)
require.ElementsMatch(t, tc.dst, dst)
})
}
}
func TestMapValues(t *testing.T) {
tests := map[string]struct {
src map[string]int
dst []int
}{
"nil map": {
src: nil,
dst: []int{},
},
"empty map": {
src: map[string]int{},
dst: []int{},
},
"filled map": {
src: map[string]int{
"foo": 1,
"bar": 2,
"baz": 3,
},
dst: []int{1, 2, 3},
},
}
for name, tc := range tests {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
dst := MapValues(tc.src)
require.ElementsMatch(t, tc.dst, dst)
})
}
}
func TestInvertMap(t *testing.T) {
tests := map[string]struct {
src map[string]int
dst map[int]string
}{
"nil map": {
src: nil,
dst: nil,
},
"empty map": {
src: map[string]int{},
dst: map[int]string{},
},
"filled map": {
src: map[string]int{
"foo": 1,
"bar": 2,
"baz": 3,
},
dst: map[int]string{
1: "foo",
2: "bar",
3: "baz",
},
},
}
for name, tc := range tests {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
dst := InvertMap(tc.src)
if tc.dst == nil {
require.Nil(t, dst)
return
}
require.NotNil(t, dst)
require.EqualValues(t, tc.dst, dst)
})
}
}