Skip to content

Commit

Permalink
Add Concat and Merge functions (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
mokiat authored Aug 9, 2023
1 parent ea07be7 commit a3317dc
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
31 changes: 31 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,34 @@ func ExampleEntries() {
// Output:
// [{Key:even Value:[2 4 6]} {Key:odd Value:[1 3 5]}]
}

func ExampleConcat() {
first := []int{1, 2}
second := []int{3, 4}
result := gog.Concat(first, second)
fmt.Printf("%#v\n", result)

// Output:
// []int{1, 2, 3, 4}
}

func ExampleMerge() {
first := map[int]string{
1: "odd",
2: "even",
}
second := map[int]string{
1: "small",
10000: "large",
}
result := gog.Merge(first, second)

fmt.Printf("1: %#v\n", result[1])
fmt.Printf("2: %#v\n", result[2])
fmt.Printf("10000: %#v\n", result[10000])

// Output:
// 1: "small"
// 2: "even"
// 10000: "large"
}
36 changes: 36 additions & 0 deletions slice.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package gog

import "golang.org/x/exp/maps"

// Map can be used to transform one slice into another by providing a
// function to do the mapping.
func Map[S, T any](slice []S, fn func(S) T) []T {
Expand Down Expand Up @@ -142,3 +144,37 @@ func DerefElements[T any](slice []*T) []T {
}
return result
}

// Concat takes a series of slices and concatenates them into one single
// slice.
//
// This function always allocates a brand new slice with appropriate
// capacity and never mutates any of the passed slices.
func Concat[T any](slices ...[]T) []T {
capacity := 0
for _, slice := range slices {
capacity += len(slice)
}

result := make([]T, 0, capacity)
for _, slice := range slices {
result = append(result, slice...)
}
return result
}

// Merge takes a series of maps and merges them into a single map.
//
// If there are overlapping keys, then latter maps overwrite former maps.
func Merge[K comparable, V any](ms ...map[K]V) map[K]V {
capacity := 0
for _, m := range ms {
capacity += len(m)
}

result := make(map[K]V, capacity)
for _, m := range ms {
maps.Copy(result, m)
}
return result
}
42 changes: 42 additions & 0 deletions slice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,4 +238,46 @@ var _ = Describe("Slice", func() {
Expect(valueSlice).To(ConsistOf(first, second, third))
})
})

Describe("Concat", func() {
It("returns a concatenation of slices", func() {
first := []int{1, 2, 3}
second := []int{4}
third := []int{5, 6, 7}
result := gog.Concat(first, second, third)
Expect(result).To(Equal([]int{1, 2, 3, 4, 5, 6, 7}))
Expect(result).To(HaveCap(7))
})

It("returns an empty slice when called without args", func() {
result := gog.Concat[int]()
Expect(result).To(Equal([]int{}))
})
})

Describe("Merge", func() {
It("returns the combination of maps", func() {
first := map[int]string{
1: "one",
2: "two",
3: "three",
}
second := map[int]string{
1: "first",
4: "fourth",
}
result := gog.Merge(first, second)
Expect(result).To(Equal(map[int]string{
1: "first",
2: "two",
3: "three",
4: "fourth",
}))
})

It("returns an empty map when called without args", func() {
result := gog.Merge[int, string]()
Expect(result).To(Equal(map[int]string{}))
})
})
})

0 comments on commit a3317dc

Please sign in to comment.