From 01f38da3aeab81823db242de1f379e92270d79b6 Mon Sep 17 00:00:00 2001 From: "Zhang Jie (Jason)" Date: Sun, 27 Aug 2023 10:47:07 +0800 Subject: [PATCH 1/5] Add new method Concat --- slice.go | 15 +++++++++++++++ slice_test.go | 12 ++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/slice.go b/slice.go index 49c991f8..8edb1f37 100644 --- a/slice.go +++ b/slice.go @@ -592,3 +592,18 @@ func IsSortedByKey[T any, K constraints.Ordered](collection []T, iteratee func(i return true } + +// Concat returns a new slice containing all the elements in `collection` plus items +func Concat[T any](collection []T, items ...T) []T { + result := make([]T, len(collection)+len(items)) + + for i := 0; i < len(collection); i++ { + result[i] = collection[i] + } + + for i := 0; i < len(items); i++ { + result[len(collection)+i] = items[i] + } + + return result +} diff --git a/slice_test.go b/slice_test.go index 03326a01..67e0fa8e 100644 --- a/slice_test.go +++ b/slice_test.go @@ -388,7 +388,7 @@ func TestAssociate(t *testing.T) { func TestSliceToMap(t *testing.T) { t.Parallel() - + type foo struct { baz string bar int @@ -626,7 +626,7 @@ func TestSlice(t *testing.T) { out16 := Slice(in, -10, 1) out17 := Slice(in, -1, 3) out18 := Slice(in, -10, 7) - + is.Equal([]int{}, out1) is.Equal([]int{0}, out2) is.Equal([]int{0, 1, 2, 3, 4}, out3) @@ -759,3 +759,11 @@ func TestIsSortedByKey(t *testing.T) { return ret })) } + +func TestConcat(t *testing.T) { + t.Parallel() + is := assert.New(t) + + is.Equal([]int{1, 2, 3, 4}, Concat([]int{1, 2}, 3, 4)) + is.Equal([]int{1, 2}, Concat(nil, 1, 2)) +} From 0379f8715612c9c8025872b2883a890f43909c87 Mon Sep 17 00:00:00 2001 From: Samuel Berthe Date: Sat, 29 Jun 2024 21:47:33 +0200 Subject: [PATCH 2/5] Update slice.go --- slice.go | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/slice.go b/slice.go index 8edb1f37..7616cac0 100644 --- a/slice.go +++ b/slice.go @@ -529,6 +529,23 @@ func Slice[T any](collection []T, start int, end int) []T { return collection[start:end] } +// Concat returns a new slice containing all the elements in +// collections. Concat conserves the order of the elements. +func Concat[T any](collections ...[]T) []T { + size := 0 + for i := range collections { + size += len(collections[i]) + } + + result := make([]T, 0, size) // preallocate memory for the output slice + for i := 0; i < len(collections); i++ { + // `result` memory address is not expected to change, because we preallocated enough memory + result = append(result, collections[i]...) + } + + return result +} + // Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new. // Play: https://go.dev/play/p/XfPzmf9gql6 func Replace[T comparable](collection []T, old T, new T, n int) []T { @@ -592,18 +609,3 @@ func IsSortedByKey[T any, K constraints.Ordered](collection []T, iteratee func(i return true } - -// Concat returns a new slice containing all the elements in `collection` plus items -func Concat[T any](collection []T, items ...T) []T { - result := make([]T, len(collection)+len(items)) - - for i := 0; i < len(collection); i++ { - result[i] = collection[i] - } - - for i := 0; i < len(items); i++ { - result[len(collection)+i] = items[i] - } - - return result -} From e56963a62f8875bb6b956b18b902d4942a490ed2 Mon Sep 17 00:00:00 2001 From: Samuel Berthe Date: Sat, 29 Jun 2024 21:48:48 +0200 Subject: [PATCH 3/5] Update slice_test.go --- slice_test.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/slice_test.go b/slice_test.go index 67e0fa8e..593d1496 100644 --- a/slice_test.go +++ b/slice_test.go @@ -647,6 +647,16 @@ func TestSlice(t *testing.T) { is.Equal([]int{0, 1, 2, 3, 4}, out18) } +func TestConcat(t *testing.T) { + t.Parallel() + is := assert.New(t) + + is.Equal([]int{1, 2, 3, 4}, Concat([]int{1, 2}, []int{3, 4})) + is.Equal([]int{1, 2, 3, 4}, Concat([]int{1, 2}, []int{3, 4})) + is.Equal([]int{}, Concat[int](nil, nil)) + is.Equal([]int{}, Concat[int]()) +} + func TestReplace(t *testing.T) { t.Parallel() is := assert.New(t) @@ -759,11 +769,3 @@ func TestIsSortedByKey(t *testing.T) { return ret })) } - -func TestConcat(t *testing.T) { - t.Parallel() - is := assert.New(t) - - is.Equal([]int{1, 2, 3, 4}, Concat([]int{1, 2}, 3, 4)) - is.Equal([]int{1, 2}, Concat(nil, 1, 2)) -} From 73af310389ae5dc0d2c140bcc99fbdd5dc22e278 Mon Sep 17 00:00:00 2001 From: Samuel Berthe Date: Sat, 29 Jun 2024 21:51:45 +0200 Subject: [PATCH 4/5] Update slice_test.go --- slice_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slice_test.go b/slice_test.go index 593d1496..3e223062 100644 --- a/slice_test.go +++ b/slice_test.go @@ -652,7 +652,7 @@ func TestConcat(t *testing.T) { is := assert.New(t) is.Equal([]int{1, 2, 3, 4}, Concat([]int{1, 2}, []int{3, 4})) - is.Equal([]int{1, 2, 3, 4}, Concat([]int{1, 2}, []int{3, 4})) + is.Equal([]int{1, 2, 3, 4}, Concat(nil, []int{1, 2}, nil, []int{3, 4}, nil)) is.Equal([]int{}, Concat[int](nil, nil)) is.Equal([]int{}, Concat[int]()) } From 885bac9acba76d2f6eb370b3c59b5716f00edafd Mon Sep 17 00:00:00 2001 From: Samuel Berthe Date: Sat, 29 Jun 2024 21:52:50 +0200 Subject: [PATCH 5/5] Update README.md --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index eddbdecb..7497ae98 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ Supported helpers for slices: - [CountValuesBy](#countvaluesby) - [Subset](#subset) - [Slice](#slice) +- [Concat](#concat) - [Replace](#replace) - [ReplaceAll](#replaceall) - [Compact](#compact) @@ -848,6 +849,21 @@ slice := lo.Slice(in, 4, 3) [[play](https://go.dev/play/p/8XWYhfMMA1h)] +### Concat + +Returns a new slice containing all the elements in collections. Concat conserves the order of the elements. + +```go +slice := lo.Concat([]int{1, 2}, []int{3, 4}) +// []int{1, 2, 3, 4} + +slice := lo.Concat(nil, []int{1, 2}, nil, []int{3, 4}, nil) +// []int{1, 2, 3, 4} + +slice := lo.Concat[int]() +// []int{} +``` + ### Replace Returns a copy of the slice with the first n non-overlapping instances of old replaced by new.