diff --git a/go.work b/go.work index f56dbda..3874a99 100644 --- a/go.work +++ b/go.work @@ -1,9 +1,10 @@ -go 1.22.2 +go 1.22.3 use ( ./xmaps ./xmath ./xnet/xhttp + ./xslices ./xslog ./xstrconv ) diff --git a/xslices/README.md b/xslices/README.md new file mode 100644 index 0000000..ca59481 --- /dev/null +++ b/xslices/README.md @@ -0,0 +1,7 @@ +# xslices +Extensions to the standard Go library's `slices` package. + +### Install +``` +go get github.com/kucherenkovova/gopypaste/xslices@v0.1.0 +``` \ No newline at end of file diff --git a/xslices/go.mod b/xslices/go.mod new file mode 100644 index 0000000..7cbc325 --- /dev/null +++ b/xslices/go.mod @@ -0,0 +1,3 @@ +module github.com/kucherenkovova/gopypaste/xslices + +go 1.22.3 diff --git a/xslices/slices.go b/xslices/slices.go new file mode 100644 index 0000000..170d828 --- /dev/null +++ b/xslices/slices.go @@ -0,0 +1,23 @@ +package xslices + +// Unique returns a new slice containing only the unique elements of the input slice. +// Only first occurrence of each element is preserved. +func Unique[T comparable](list []T) []T { + if list == nil { + return nil + } + + seen := make(map[T]struct{}, len(list)) + results := make([]T, 0, len(list)) + + for _, element := range list { + if _, ok := seen[element]; ok { + continue + } + + seen[element] = struct{}{} + results = append(results, element) + } + + return results +} diff --git a/xslices/slices_test.go b/xslices/slices_test.go new file mode 100644 index 0000000..e62b489 --- /dev/null +++ b/xslices/slices_test.go @@ -0,0 +1,52 @@ +package xslices_test + +import ( + "reflect" + "testing" + + "github.com/kucherenkovova/gopypaste/xslices" +) + +func TestUnique(t *testing.T) { + type testCase struct { + name string + in []string + want []string + } + + tests := []testCase{ + { + name: "empty list", + in: []string{}, + want: []string{}, + }, + { + name: "nil", + in: nil, + want: nil, + }, + { + name: "no duplicates", + in: []string{"a", "b", "c"}, + want: []string{"a", "b", "c"}, + }, + { + name: "consequent duplicates", + in: []string{"a", "a", "b", "b", "c", "c"}, + want: []string{"a", "b", "c"}, + }, + { + name: "non-consequent duplicates", + in: []string{"a", "b", "a", "c", "b", "c"}, + want: []string{"a", "b", "c"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := xslices.Unique(tt.in); !reflect.DeepEqual(got, tt.want) { + t.Errorf("Unique() = %v, want %v", got, tt.want) + } + }) + } +}