Skip to content

Commit

Permalink
feat(slices): Added Map/Each/Filter/Reduce and so on... (#156)
Browse files Browse the repository at this point in the history
* feat(slices): Added `Map`

Signed-off-by: Flc゛ <[email protected]>

* feat(slices): Added `Map`/`Each`/`Filter`/`Reduce`/`Reverse`/`Concat`/`IsEmpty`/`IsNotEmpty`

Signed-off-by: Flc゛ <[email protected]>

---------

Signed-off-by: Flc゛ <[email protected]>
  • Loading branch information
flc1125 authored Mar 15, 2024
1 parent bb410a7 commit a3b6202
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 0 deletions.
56 changes: 56 additions & 0 deletions slices/slices.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package slices

func Map[S ~[]E, E, R any](s S, fn func(E) R) []R {
result := make([]R, 0, len(s))
for _, item := range s {
result = append(result, fn(item))
}
return result
}

func Each[S ~[]E, E any](s S, fn func(E)) {
for _, item := range s {
fn(item)
}
}

func Filter[S ~[]E, E any](s S, fn func(E) bool) []E {
var result []E
for _, item := range s {
if fn(item) {
result = append(result, item)
}
}
return result
}

func Reduce[S ~[]E, E, R any](s S, fn func(R, E) R) R {
var result R
for _, item := range s {
result = fn(result, item)
}
return result
}

func Reverse[S ~[]E, E any](s S) S {
result := make(S, len(s))
for i := 0; i < len(s); i++ {
result[i] = s[len(s)-1-i]
}
return result
}

func Concat[S ~[]E, E any](s1, s2 S) S {
result := make(S, 0, len(s1)+len(s2))
result = append(result, s1...)
result = append(result, s2...)
return result
}

func IsEmpty[S ~[]E, E any](s S) bool {
return len(s) == 0
}

func IsNotEmpty[S ~[]E, E any](s S) bool {
return len(s) > 0
}
115 changes: 115 additions & 0 deletions slices/slices_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package slices

import (
"strconv"
"testing"

"github.com/stretchr/testify/assert"
)

type T struct {
A string
}

func TestMap(t *testing.T) {
s1 := []int{1, 2, 3, 4, 5}
assert.Equal(t, []int{2, 4, 6, 8, 10}, Map(s1, func(n int) int { return n * 2 }))

s2 := []int{1, 2, 3, 4, 5}
assert.Equal(t, []string{"1", "2", "3", "4", "5"}, Map(s2, strconv.Itoa))

s3 := []string{"1", "2", "3", "4", "5"}
assert.Equal(t, []T{{"1"}, {"2"}, {"3"}, {"4"}, {"5"}}, Map(s3, func(s string) T { return T{s} }))
}

func TestEach(t *testing.T) {
s1 := []int{1, 2, 3, 4, 5}
var result []int
Each(s1, func(n int) { result = append(result, n*2) })
assert.Equal(t, []int{2, 4, 6, 8, 10}, result)

s2 := []int{1, 2, 3, 4, 5}
var result2 []string
Each(s2, func(n int) { result2 = append(result2, strconv.Itoa(n)) })
assert.Equal(t, []string{"1", "2", "3", "4", "5"}, result2)

s3 := []string{"1", "2", "3", "4", "5"}
var result3 []T
Each(s3, func(s string) { result3 = append(result3, T{s}) })
}

func TestFilter(t *testing.T) {
s1 := []int{1, 2, 3, 4, 5}
assert.Equal(t, []int{2, 4}, Filter(s1, func(n int) bool { return n%2 == 0 }))

s2 := []int{1, 2, 3, 4, 5}
assert.Equal(t, []int{1, 3, 5}, Filter(s2, func(n int) bool { return n%2 != 0 }))

s3 := []string{"1", "2", "3", "4", "5"}
assert.Equal(t, []string{"1", "2", "3"}, Filter(s3, func(s string) bool { return s < "4" }))

s4 := []T{{"1"}, {"2"}, {"3"}, {"4"}, {"5"}}
assert.Equal(t, []T{{"1"}, {"2"}, {"3"}}, Filter(s4, func(t T) bool { return t.A < "4" }))
}

func TestReduce(t *testing.T) {
s1 := []int{1, 2, 3, 4, 5}
assert.Equal(t, 15, Reduce(s1, func(acc, n int) int { return acc + n }))

s2 := []int{1, 2, 3, 4, 5}
assert.Equal(t, 0, Reduce(s2, func(acc, n int) int { return acc * n }))

s3 := []string{"1", "2", "3", "4", "5"}
assert.Equal(t, "12345", Reduce(s3, func(acc, s string) string { return acc + s }))
}

func TestReverse(t *testing.T) {
s1 := []int{1, 2, 3, 4, 5}
assert.Equal(t, []int{5, 4, 3, 2, 1}, Reverse(s1))

s2 := []string{"1", "2", "3", "4", "5"}
assert.Equal(t, []string{"5", "4", "3", "2", "1"}, Reverse(s2))

s3 := []T{{"1"}, {"2"}, {"3"}, {"4"}, {"5"}}
assert.Equal(t, []T{{"5"}, {"4"}, {"3"}, {"2"}, {"1"}}, Reverse(s3))
}

func TestConcat(t *testing.T) {
s1 := []int{1, 2, 3}
s2 := []int{4, 5, 6}
assert.Equal(t, []int{1, 2, 3, 4, 5, 6}, Concat(s1, s2))

s3 := []string{"1", "2", "3"}
s4 := []string{"4", "5", "6"}
assert.Equal(t, []string{"1", "2", "3", "4", "5", "6"}, Concat(s3, s4))

s5 := []T{{"1"}, {"2"}, {"3"}}
s6 := []T{{"4"}, {"5"}, {"6"}}
assert.Equal(t, []T{{"1"}, {"2"}, {"3"}, {"4"}, {"5"}, {"6"}}, Concat(s5, s6))
}

func TestIsEmptyAndIsNotEmpty(t *testing.T) {
s1 := []int{1, 2, 3}
assert.False(t, IsEmpty(s1))
assert.True(t, IsNotEmpty(s1))

var s2 []int
assert.True(t, IsEmpty(s2))
assert.False(t, IsNotEmpty(s2))

s3 := []string{"1", "2", "3"}
assert.False(t, IsEmpty(s3))
assert.True(t, IsNotEmpty(s3))

var s4 []string
assert.True(t, IsEmpty(s4))
assert.False(t, IsNotEmpty(s4))

s5 := []T{{"1"}, {"2"}, {"3"}}
assert.False(t, IsEmpty(s5))
assert.True(t, IsNotEmpty(s5))

var s6 []T
assert.True(t, IsEmpty(s6))
assert.False(t, IsNotEmpty(s6))
}

0 comments on commit a3b6202

Please sign in to comment.