From 6853d627f457369e179edfcc5ab4e3811a3f7ec4 Mon Sep 17 00:00:00 2001 From: Cannian <2081215119@qq.com> Date: Sat, 6 Apr 2024 09:16:28 +0800 Subject: [PATCH] refactor(slice): optimize function (#211) --- slice/slice.go | 43 ++++++++++++++++++++++++++++++++----------- slice/slice_test.go | 16 ++++++++++++++-- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/slice/slice.go b/slice/slice.go index d832a369..4d63ec3a 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -50,12 +50,23 @@ func ContainBy[T any](slice []T, predicate func(item T) bool) bool { // ContainSubSlice check if the slice contain a given subslice or not. // Play: https://go.dev/play/p/bcuQ3UT6Sev func ContainSubSlice[T comparable](slice, subSlice []T) bool { - for _, v := range subSlice { - if !Contain(slice, v) { + if len(subSlice) == 0 { + return true + } + if len(slice) == 0 { + return false + } + + elementMap := make(map[T]struct{}, len(slice)) + for _, item := range slice { + elementMap[item] = struct{}{} + } + + for _, item := range subSlice { + if _, ok := elementMap[item]; !ok { return false } } - return true } @@ -81,35 +92,41 @@ func Chunk[T any](slice []T, size int) [][]T { return result } -// Compact creates an slice with all falsey values removed. The values false, nil, 0, and "" are falsey. +// Compact creates a slice with all falsey values removed. The values false, nil, 0, and "" are falsey. // Play: https://go.dev/play/p/pO5AnxEr3TK func Compact[T comparable](slice []T) []T { var zero T - result := []T{} + result := make([]T, 0, len(slice)) for _, v := range slice { if v != zero { result = append(result, v) } } - - return result + return result[:len(result):len(result)] } // Concat creates a new slice concatenating slice with any additional slices. // Play: https://go.dev/play/p/gPt-q7zr5mk func Concat[T any](slice []T, slices ...[]T) []T { - result := append([]T{}, slice...) + totalLen := len(slice) for _, v := range slices { - result = append(result, v...) + totalLen += len(v) + } + + result := make([]T, 0, totalLen) + + result = append(result, slice...) + for _, s := range slices { + result = append(result, s...) } return result } -// Difference creates an slice of whose element in slice but not in comparedSlice. +// Difference creates a slice of whose element in slice but not in comparedSlice. // Play: https://go.dev/play/p/VXvadzLzhDa func Difference[T comparable](slice, comparedSlice []T) []T { result := []T{} @@ -826,7 +843,11 @@ func UnionBy[T any, V comparable](predicate func(item T) V, slices ...[]T) []T { // Merge all given slices into one slice. // Play: https://go.dev/play/p/lbjFp784r9N func Merge[T any](slices ...[]T) []T { - result := make([]T, 0) + totalLen := 0 + for _, v := range slices { + totalLen += len(v) + } + result := make([]T, 0, totalLen) for _, v := range slices { result = append(result, v...) diff --git a/slice/slice_test.go b/slice/slice_test.go index 5bb43e27..fb2c4e2c 100644 --- a/slice/slice_test.go +++ b/slice/slice_test.go @@ -2,12 +2,11 @@ package slice import ( "fmt" + "github.com/duke-git/lancet/v2/internal" "math" "reflect" "strconv" "testing" - - "github.com/duke-git/lancet/v2/internal" ) func TestContain(t *testing.T) { @@ -109,6 +108,19 @@ func TestConcat(t *testing.T) { assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, []int{4}, []int{5})) } +func BenchmarkConcat(b *testing.B) { + slice1 := []int{1, 2, 3} + slice2 := []int{4, 5, 6} + slice3 := []int{7, 8, 9} + + for i := 0; i < b.N; i++ { + result := Concat(slice1, slice2, slice3) + if len(result) == 0 { + b.Fatal("unexpected empty result") + } + } +} + func TestEqual(t *testing.T) { t.Parallel()