Browse code

internal/sliceutil: add utilities to map values

Functional programming for the win! Add a utility function to map the
values of a slice, along with a curried variant, to tide us over until
equivalent functionality gets added to the standard library
(https://go.dev/issue/61898)

Signed-off-by: Cory Snider <csnider@mirantis.com>

Cory Snider authored on 2024/01/25 07:56:29
Showing 2 changed files
... ...
@@ -11,3 +11,21 @@ func Dedup[T comparable](slice []T) []T {
11 11
 	}
12 12
 	return out
13 13
 }
14
+
15
+func Map[S ~[]In, In, Out any](s S, fn func(In) Out) []Out {
16
+	res := make([]Out, len(s))
17
+	for i, v := range s {
18
+		res[i] = fn(v)
19
+	}
20
+	return res
21
+}
22
+
23
+func Mapper[In, Out any](fn func(In) Out) func([]In) []Out {
24
+	return func(s []In) []Out {
25
+		res := make([]Out, len(s))
26
+		for i, v := range s {
27
+			res[i] = fn(v)
28
+		}
29
+		return res
30
+	}
31
+}
14 32
new file mode 100644
... ...
@@ -0,0 +1,49 @@
0
+package sliceutil_test
1
+
2
+import (
3
+	"net/netip"
4
+	"strconv"
5
+	"testing"
6
+
7
+	"github.com/docker/docker/internal/sliceutil"
8
+)
9
+
10
+func TestMap(t *testing.T) {
11
+	s := []int{1, 2, 3}
12
+	m := sliceutil.Map(s, func(i int) int { return i * 2 })
13
+	if len(m) != len(s) {
14
+		t.Fatalf("expected len %d, got %d", len(s), len(m))
15
+	}
16
+	for i, v := range m {
17
+		if expected := s[i] * 2; v != expected {
18
+			t.Fatalf("expected %d, got %d", expected, v)
19
+		}
20
+	}
21
+}
22
+
23
+func TestMap_TypeConvert(t *testing.T) {
24
+	s := []int{1, 2, 3}
25
+	m := sliceutil.Map(s, func(i int) string { return strconv.Itoa(i) })
26
+	if len(m) != len(s) {
27
+		t.Fatalf("expected len %d, got %d", len(s), len(m))
28
+	}
29
+	for i, v := range m {
30
+		if expected := strconv.Itoa(s[i]); v != expected {
31
+			t.Fatalf("expected %s, got %s", expected, v)
32
+		}
33
+	}
34
+}
35
+
36
+func TestMapper(t *testing.T) {
37
+	s := []string{"1.2.3.4", "fe80::1"}
38
+	mapper := sliceutil.Mapper(netip.MustParseAddr)
39
+	m := mapper(s)
40
+	if len(m) != len(s) {
41
+		t.Fatalf("expected len %d, got %d", len(s), len(m))
42
+	}
43
+	for i, v := range m {
44
+		if expected := netip.MustParseAddr(s[i]); v != expected {
45
+			t.Fatalf("expected %s, got %s", expected, v)
46
+		}
47
+	}
48
+}