From 7fb688772eea90eccb9d2562bd1e102c2f38141f Mon Sep 17 00:00:00 2001 From: clawbot Date: Sat, 5 Sep 2026 03:23:28 +0000 Subject: [PATCH] add DedupeStrings for removing repeated values from a string slice DedupeStrings returns a new slice holding each value once, in the order each value first appeared, and leaves the input slice alone. Comes with a doc comment and table-driven tests. (closes #1) Model: opus-5 --- dedupe.go | 23 +++++++++++++++++++++++ dedupe_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 dedupe.go create mode 100644 dedupe_test.go diff --git a/dedupe.go b/dedupe.go new file mode 100644 index 0000000..3803732 --- /dev/null +++ b/dedupe.go @@ -0,0 +1,23 @@ +package util + +// DedupeStrings returns a new slice holding each value of input once, in the +// order in which each value first appears. The input slice is not modified. +// A nil input returns nil. +func DedupeStrings(input []string) []string { + if input == nil { + return nil + } + + seen := make(map[string]struct{}, len(input)) + out := make([]string, 0, len(input)) + + for _, value := range input { + if _, ok := seen[value]; ok { + continue + } + seen[value] = struct{}{} + out = append(out, value) + } + + return out +} diff --git a/dedupe_test.go b/dedupe_test.go new file mode 100644 index 0000000..56e9963 --- /dev/null +++ b/dedupe_test.go @@ -0,0 +1,40 @@ +package util + +import ( + "reflect" + "testing" +) + +func TestDedupeStrings(t *testing.T) { + tests := []struct { + name string + input []string + expected []string + }{ + {"nil stays nil", nil, nil}, + {"empty slice", []string{}, []string{}}, + {"nothing repeated", []string{"a", "b", "c"}, []string{"a", "b", "c"}}, + {"all one value", []string{"a", "a", "a"}, []string{"a"}}, + {"repeats next to each other", []string{"a", "a", "b", "b"}, []string{"a", "b"}}, + {"repeats far apart", []string{"a", "b", "a", "c", "b"}, []string{"a", "b", "c"}}, + {"empty string is a value", []string{"", "a", ""}, []string{"", "a"}}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := DedupeStrings(test.input) + if !reflect.DeepEqual(got, test.expected) { + t.Errorf("expected %#v got %#v", test.expected, got) + } + }) + } +} + +func TestDedupeStringsLeavesInputAlone(t *testing.T) { + input := []string{"b", "a", "b"} + DedupeStrings(input) + + if !reflect.DeepEqual(input, []string{"b", "a", "b"}) { + t.Errorf("expected the input to be unchanged, got %#v", input) + } +} -- 2.49.1