From 4ba746956ad930cb963c4e08f75f18bfdee91d1c Mon Sep 17 00:00:00 2001 From: ScuroNeko Date: Fri, 6 Feb 2026 13:46:09 +0300 Subject: [PATCH] some testing ang enchancments --- map.go | 14 +++++++ map_test.go | 23 +++++++++++ queue.go | 4 +- queue_test.go | 49 +++++++++++++++++++++++ set.go | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ slice.go | 107 +++++++------------------------------------------- slice_test.go | 78 ++++++++++++++++++++++++++++++++++++ 7 files changed, 286 insertions(+), 94 deletions(-) create mode 100644 map_test.go create mode 100644 queue_test.go create mode 100644 set.go create mode 100644 slice_test.go diff --git a/map.go b/map.go index 4a53ef3..581a9b1 100644 --- a/map.go +++ b/map.go @@ -34,6 +34,20 @@ func (m HashMap[K, V]) Contains(key K) bool { _, ok := m[key] return ok } +func (m HashMap[K, V]) Keys() []K { + keys := make([]K, 0, m.Len()) + for k := range m { + keys = append(keys, k) + } + return keys +} +func (m HashMap[K, V]) Values() []V { + values := make([]V, 0, m.Len()) + for _, v := range m { + values = append(values, v) + } + return values +} func (m HashMap[K, V]) Filter(f func(K, V) bool) HashMap[K, V] { out := make(HashMap[K, V]) for k, v := range m { diff --git a/map_test.go b/map_test.go new file mode 100644 index 0000000..a98c613 --- /dev/null +++ b/map_test.go @@ -0,0 +1,23 @@ +package extypes + +import ( + "fmt" + "testing" +) + +func BenchmarkHashMap_Add(b *testing.B) { + b.StartTimer() + m := make(HashMap[string, string]) + for i := 0; i < b.N; i++ { + m.Add(fmt.Sprint(i), fmt.Sprint(i)) + } + b.StopTimer() +} +func BenchmarkGoMap_Add(b *testing.B) { + b.StartTimer() + m := make(map[string]string) + for i := 0; i < b.N; i++ { + m[fmt.Sprint(i)] = fmt.Sprint(i) + } + b.StopTimer() +} diff --git a/queue.go b/queue.go index 3ed4aa7..0566cbe 100644 --- a/queue.go +++ b/queue.go @@ -1,4 +1,4 @@ -package extypes +package extypes import ( "errors" @@ -15,7 +15,7 @@ type Queue[T any] struct { func CreateQueue[T any](size uint64) *Queue[T] { return &Queue[T]{ - queue: make([]T, 0), + queue: make([]T, 0, size), size: size, } } diff --git a/queue_test.go b/queue_test.go new file mode 100644 index 0000000..00b68bc --- /dev/null +++ b/queue_test.go @@ -0,0 +1,49 @@ +package extypes + +import ( + "log" + "testing" +) + +func ExampleCreateQueue() { + q := CreateQueue[int](16) + err := q.Enqueue(1) + if err != nil { + panic(err) + } + i := q.Dequeue() // <- Here we got 1 + log.Println(i) +} +func BenchmarkQueue_Enqueue(b *testing.B) { + b.StartTimer() + q := CreateQueue[int](uint64(b.N)) + for i := 0; i < b.N; i++ { + q.Enqueue(i) + } + b.StopTimer() + b.ReportAllocs() +} +func BenchmarkQueue_Dequeue(b *testing.B) { + q := CreateQueue[int](uint64(b.N)) + for i := 0; i < b.N; i++ { + q.Enqueue(i) + } + b.StartTimer() + for i := 0; i < b.N; i++ { + q.Dequeue() + } + b.StopTimer() + b.ReportAllocs() +} +func BenchmarkQueue_EnqueueDequeue(b *testing.B) { + b.StartTimer() + q := CreateQueue[int](uint64(b.N)) + for i := 0; i < b.N; i++ { + q.Enqueue(i) + } + for i := 0; i < b.N; i++ { + q.Dequeue() + } + b.StopTimer() + b.ReportAllocs() +} diff --git a/set.go b/set.go new file mode 100644 index 0000000..b2e8c57 --- /dev/null +++ b/set.go @@ -0,0 +1,105 @@ +package extypes + +import ( + "reflect" +) + +type Set[T any] []T + +func NewSetFrom[T any](slice []T) Set[T] { + s := make(Set[T], 0) + for _, v := range slice { + if s.Index(v) >= 0 { + continue + } + s = append(s, v) + } + return s +} +func (s Set[T]) Len() int { + return len(s) +} +func (s Set[T]) Cap() int { + return cap(s) +} +func (s Set[T]) Get(index int) T { + return s[index] +} +func (s Set[T]) Last() T { + return s[s.Len()-1] +} +func (s Set[T]) Index(el T) int { + for i := range s { + if reflect.DeepEqual(s[i], el) { + return i + } + } + return -1 +} +func (s Set[T]) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} +func (s Set[T]) Add(v T) Set[T] { + index := s.Index(v) + if index >= 0 { + return s + } + return append(s, v) +} +func (s Set[T]) Pop(index int) Set[T] { + if index == 0 { + return s[1:] + } + out := make(Set[T], s.Len()-1) + copy(out, s[:index]) + copy(out[index:], s[index+1:]) + return out +} +func (s Set[T]) Remove(el T) Set[T] { + index := s.Index(el) + if index == -1 { + return s + } + return s.Pop(index) +} +func (s Set[T]) Filter(f func(e T) bool) Set[T] { + out := make(Set[T], 0) + for _, v := range s { + if f(v) { + out = append(out, v) + } + } + return out +} +func (s Set[T]) ToSlice() Slice[T] { + out := make(Slice[T], s.Len()) + copy(out, s) + return out +} +func (s Set[T]) ToArray() []T { + out := make([]T, len(s)) + copy(out, s) + return out +} +func (s Set[T]) ToAnyArray() []any { + out := make([]any, len(s)) + for i, v := range s { + out[i] = v + } + return out +} + +func (s Set[T]) Equal(s2 Set[T]) bool { + if s.Len() != s2.Len() { + return false + } + if s.Cap() != s2.Cap() { + return false + } + for i := range s { + if !reflect.DeepEqual(s[i], s2[i]) { + return false + } + } + return true +} diff --git a/slice.go b/slice.go index bee26d8..d9961bc 100644 --- a/slice.go +++ b/slice.go @@ -2,7 +2,6 @@ package extypes import ( "reflect" - "slices" ) type Slice[T any] []T @@ -26,17 +25,11 @@ func (s Slice[T]) Last() T { } func (s Slice[T]) Index(el T) int { for i := range s { - //t1 := reflect.TypeOf(el) - //t2 := reflect.TypeOf(s[i]) - //if t1 != t2 { - // continue - //} if reflect.DeepEqual(s[i], el) { return i } } return -1 - //return slices.Index(s, el) } // Swap is mutable func @@ -64,13 +57,9 @@ func (s Slice[T]) Pop(index int) Slice[T] { if index == 0 { return s[1:] } - out := make(Slice[T], 0, s.Len()-1) - for i, e := range s { - if i == index { - continue - } - out = append(out, e) - } + out := make(Slice[T], s.Len()-1) + copy(out, s[:index]) + copy(out[index:], s[index+1:]) return out } func (s Slice[T]) Remove(el T) Slice[T] { @@ -96,6 +85,9 @@ func (s Slice[T]) ToAnyArray() []any { } return out } +func (s Slice[T]) ToSet() Set[T] { + return NewSetFrom(s) +} // ForEach is mutable func func (s Slice[T]) ForEach(f func(e T) T) Slice[T] { @@ -105,86 +97,17 @@ func (s Slice[T]) ForEach(f func(e T) T) Slice[T] { return s } -type Set[T comparable] []T - -func NewSetFrom[T comparable](slice []T) Set[T] { - s := make(Set[T], 0) - for _, v := range slice { - if s.Index(v) >= 0 { - continue - } - s = append(s, v) +func (s Slice[T]) Equal(s2 Slice[T]) bool { + if s.Len() != s2.Len() { + return false } - return s -} -func (s Set[T]) Len() int { - return len(s) -} -func (s Set[T]) Cap() int { - return cap(s) -} -func (s Set[T]) Get(index int) T { - return s[index] -} -func (s Set[T]) Last() T { - return s[s.Len()-1] -} -func (s Set[T]) Index(el T) int { - return slices.Index(s, el) -} -func (s Set[T]) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} -func (s Set[T]) Add(v T) Set[T] { - index := s.Index(v) - if index >= 0 { - return s + if s.Cap() != s2.Cap() { + return false } - return append(s, v) -} -func (s Set[T]) Pop(index int) Set[T] { - if index == 0 { - return s[1:] - } - out := make(Set[T], 0, s.Len()-1) - for i, e := range s { - if i == index { - continue - } - out = append(out, e) - } - return out -} -func (s Set[T]) Remove(el T) Set[T] { - index := s.Index(el) - if index == -1 { - return s - } - return s.Pop(index) -} -func (s Set[T]) Filter(f func(e T) bool) Set[T] { - out := make(Set[T], 0) - for _, v := range s { - if f(v) { - out = append(out, v) + for i := range s { + if !reflect.DeepEqual(s[i], s2[i]) { + return false } } - return out -} -func (s Set[T]) ToSlice() Slice[T] { - out := make(Slice[T], s.Len()) - copy(out, s) - return out -} -func (s Set[T]) ToArray() []T { - out := make([]T, len(s)) - copy(out, s) - return out -} -func (s Set[T]) ToAnyArray() []any { - out := make([]any, len(s)) - for i, v := range s { - out[i] = v - } - return out + return true } diff --git a/slice_test.go b/slice_test.go new file mode 100644 index 0000000..3258d45 --- /dev/null +++ b/slice_test.go @@ -0,0 +1,78 @@ +package extypes + +import ( + "fmt" + "testing" +) + +type A struct { + i int + b bool + s string +} + +func TestSlice_Index(t *testing.T) { + s := make(Slice[int], 10) + for i := 0; i < 10; i++ { + s[i] = i + 1 + } + + if s.Index(0) != -1 { + t.Errorf("s.Index(0) != -1") + } + if s.Index(5) != 4 { + t.Errorf("s.Index(5) != 4") + } + + s2 := make(Slice[A], 5) + for i := 0; i < 5; i++ { + s2[i] = A{i + 1, false, fmt.Sprint(i)} + } + if s2.Index(A{2, false, "1"}) != 1 { + t.Errorf("s2 wrong index") + } +} +func TestSlice_Equal(t *testing.T) { + a1 := make(Slice[int], 10) + a2 := make(Slice[int], 10) + a3 := make(Slice[int], 5) + + for i := 0; i < 10; i++ { + a1[i] = i + a2[i] = i + 1 + } + for i := 0; i < 5; i++ { + a3[i] = i + } + + if a1.Equal(a2) { + t.Errorf("a1 == a2") + } + if a1.Equal(a3) { + t.Errorf("a1 == a3") + } + if a2.Equal(a3) { + t.Errorf("a2 == a3") + } +} + +func TestSlice_Pop(t *testing.T) { + a1 := make(Slice[int], 10) + a2 := make(Slice[int], 9) + + for i := 0; i < 10; i++ { + a1[i] = i + } + for i := 0; i < 9; i++ { + a2[i] = i + } + + a1 = a1.Pop(a1.Len() - 1) + + if a1.Len() != 9 { + t.Errorf("a1.Len() != 9") + } + if !a1.Equal(a2) { + t.Errorf("a1 != a2") + } +}