diff --git a/pkg/collection/collection.go b/pkg/collection/collection.go index 0f62c78..75935ca 100644 --- a/pkg/collection/collection.go +++ b/pkg/collection/collection.go @@ -25,6 +25,7 @@ type List[E any] interface { Front() (E, error) PushBack(item E) PushFront(item E) + Set(item E, pos int) error Index(item E) (int, error) GetAt(pos int) (E, error) PushAt(item E, pos int) diff --git a/pkg/collection/linked_list.go b/pkg/collection/linked_list.go index 719dec8..ed47a33 100644 --- a/pkg/collection/linked_list.go +++ b/pkg/collection/linked_list.go @@ -230,6 +230,20 @@ func (l *LinkedList[E]) DeleteAt(pos int) error { return nil } +func (l *LinkedList[E]) Set(item E, pos int) error { + n, err := l.findNode(pos) + if err != nil { + return err + } + + if n == nil { + return ErrNodeNotFound + } + + n.value = item + return nil +} + func (l *LinkedList[E]) String() string { var sb strings.Builder sb.WriteString("[") diff --git a/pkg/collection/linked_list_test.go b/pkg/collection/linked_list_test.go index 574f359..4bf8fd6 100644 --- a/pkg/collection/linked_list_test.go +++ b/pkg/collection/linked_list_test.go @@ -230,6 +230,63 @@ func TestLinkedList_PushFront(t *testing.T) { } } +func TestLinkedList_Set(t *testing.T) { + useCases := []struct { + description string + original *LinkedList[int] + modified *LinkedList[int] + pos int + item int + err error + }{ + {description: "change item in first position in singleton list", + original: NewLinkedList[int](0), + modified: NewLinkedList(1), + pos: 0, + item: 1}, + {description: "change item in first position in full list", + original: NewLinkedList(1, 2, 3), + modified: NewLinkedList(0, 2, 3), + pos: 0, + item: 0}, + {description: "change item in middle position in full list", + original: NewLinkedList(1, 2, 3), + modified: NewLinkedList(1, 0, 3), + pos: 1, + item: 0}, + {description: "add item in last position in full list", + original: NewLinkedList(1, 2, 3), + modified: NewLinkedList(1, 2, 0), + pos: 2, + item: 0}, + {description: "no items in list return ErrEmptyCollection", + original: NewLinkedList[int](), + modified: NewLinkedList[int](), + pos: 0, + item: 0, + err: ErrEmptyCollection}, + {description: "get item with negative position", + original: NewLinkedList(1, 2, 3), + modified: NewLinkedList(1, 2, 3), + pos: -1, + item: 0, + err: ErrPositionNegative}, + {description: "get item with index out of bound", + original: NewLinkedList(1, 2, 3), + modified: NewLinkedList(1, 2, 3), + pos: 4, + item: 0, + err: ErrIndexOutOfBound{4, 3}}, + } + + for _, tt := range useCases { + err := tt.original.Set(tt.item, tt.pos) + if !compareLists(tt.original, tt.modified) || tt.err != err { + t.Errorf("test: %s want %v got %v", tt.description, tt.modified, tt.original) + } + } +} + func TestLinkedList_Delete(t *testing.T) { useCases := []struct { description string diff --git a/pkg/collection/slice.go b/pkg/collection/slice.go index 21bf2b8..dc9a6ff 100644 --- a/pkg/collection/slice.go +++ b/pkg/collection/slice.go @@ -158,6 +158,20 @@ func (s *Slice[E]) Index(item E) (int, error) { return 0, ErrItemNotFound{item} } +func (s *Slice[E]) Set(item E, pos int) error { + if s.Empty() { + return ErrEmptyCollection + } + if pos < 0 { + return ErrPositionNegative + } + if pos < 0 || pos >= s.Size() { + return ErrIndexOutOfBound{pos, s.Size()} + } + s.inner[pos] = item + return nil +} + func (s *Slice[E]) String() string { var sb strings.Builder sb.WriteString("[") diff --git a/pkg/collection/slice_test.go b/pkg/collection/slice_test.go index fa01cc2..758cb68 100644 --- a/pkg/collection/slice_test.go +++ b/pkg/collection/slice_test.go @@ -328,3 +328,60 @@ func TestSlice_Index(t *testing.T) { } } } + +func TestSlice_Set(t *testing.T) { + useCases := []struct { + description string + original *Slice[int] + modified *Slice[int] + pos int + item int + err error + }{ + {description: "change item in first position in singleton list", + original: NewSlice[int](0), + modified: NewSlice(1), + pos: 0, + item: 1}, + {description: "change item in first position in full list", + original: NewSlice(1, 2, 3), + modified: NewSlice(0, 2, 3), + pos: 0, + item: 0}, + {description: "change item in middle position in full list", + original: NewSlice(1, 2, 3), + modified: NewSlice(1, 0, 3), + pos: 1, + item: 0}, + {description: "add item in last position in full list", + original: NewSlice(1, 2, 3), + modified: NewSlice(1, 2, 0), + pos: 2, + item: 0}, + {description: "no items in list return ErrEmptyCollection", + original: NewSlice[int](), + modified: NewSlice[int](), + pos: 0, + item: 0, + err: ErrEmptyCollection}, + {description: "get item with negative position", + original: NewSlice(1, 2, 3), + modified: NewSlice(1, 2, 3), + pos: -1, + item: 0, + err: ErrPositionNegative}, + {description: "get item with index out of bound", + original: NewSlice(1, 2, 3), + modified: NewSlice(1, 2, 3), + pos: 4, + item: 0, + err: ErrIndexOutOfBound{4, 3}}, + } + + for _, tt := range useCases { + err := tt.original.Set(tt.item, tt.pos) + if !reflect.DeepEqual(tt.original, tt.modified) || tt.err != err { + t.Errorf("test: %s want %v got %v", tt.description, tt.modified, tt.original) + } + } +}