Skip to content

Commit

Permalink
Merge pull request #10 from devalexandre/feat/chain
Browse files Browse the repository at this point in the history
Feat/chain
  • Loading branch information
devalexandre authored Sep 26, 2023
2 parents 86e47de + efb2642 commit 81a9cf3
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 118 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,17 +384,16 @@ type Itens struct {
You can chain the functions together.

```go
data := array.Array[int]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

a := array.NewArray(data).
a := data.
Filter(func(i int) bool {
return i%2 == 0
}).
Map(func(i int) int {
return i * 2
}).
Value()


fmt.Println(a) // [4 8 12 16 20]

Expand Down
60 changes: 27 additions & 33 deletions array/array.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,62 +8,56 @@ package array
*/

type Array[T any] struct {
value []T
}

func NewArray[T any](a []T) *Array[T] {
return &Array[T]{value: a}
}
type Array[T any] []T

func (a *Array[T]) Value() []T {
return a.value
func (a Array[T]) Length() int {
return len(a)
}

func (a *Array[T]) Length() int {
return len(a.value)
func (a Array[T]) Filter(f func(T) bool) Array[T] {
return Filter(a, f)
}

func (a *Array[T]) Filter(f func(T) bool) *Array[T] {
return &Array[T]{value: Filter(a.value, f)}
func (a Array[T]) Find(f func(T) bool) T {
return Find(a, f)
}

func (a *Array[T]) Find(f func(T) bool) (T, bool) {
return Find(a.value, f)
func (a Array[T]) Map(f func(T) T) Array[T] {
return Map(a, f)
}

func (a *Array[T]) Map(f func(T) T) *Array[T] {
return &Array[T]{value: Map(a.value, f)}
func (a Array[T]) FlatMap(f func(T) []T) Array[T] {
return FlatMap(a, f)
}

func (a *Array[T]) FlatMap(f func(T) []T) *Array[T] {
return &Array[T]{value: FlatMap(a.value, f)}
func (a Array[T]) Reduce(f func(T, T) T) T {
return Reduce(a, f)
}

func (a *Array[T]) Reduce(f func(T, T) T) T {
return Reduce(a.value, f)
func (a Array[T]) Reverse() Array[T] {
return Reverse(a)
}

func (a *Array[T]) Reverse() *Array[T] {
return &Array[T]{value: Reverse(a.value)}
func (a Array[T]) Any(f func(T) bool) bool {
return Any(a, f)
}

func (a *Array[T]) Any(f func(T) bool) bool {
return Any(a.value, f)
func (a Array[T]) Some(f func(T) bool) bool {
return Some(a, f)
}

func (a *Array[T]) Some(f func(T) bool) bool {
return Some(a.value, f)
func (a Array[T]) Every(f func(T) bool) bool {
return Every(a, f)
}

func (a *Array[T]) Every(f func(T) bool) bool {
return Every(a.value, f)
func (a Array[T]) Shuffle() Array[T] {
return Shuffle(a)
}

func (a *Array[T]) Shuffle() *Array[T] {
return &Array[T]{value: Shuffle(a.value)}
func (a Array[T]) Sort(f func(i, j int) bool) Array[T] {
return Sort(a, f)
}

func (a *Array[T]) Sort(f func(i, j int) bool) *Array[T] {
return &Array[T]{value: Sort(a.value, f)}
func (a Array[T]) GroupBy(f func(T) string) map[string][]T {
return GroupBy(a, f)
}
111 changes: 75 additions & 36 deletions array/array_test.go
Original file line number Diff line number Diff line change
@@ -1,90 +1,106 @@
package array_test

import (
"fmt"
"github.com/devalexandre/gofn/array"
"reflect"
"testing"
)

func TestArray(t *testing.T) {
t.Run("test Filter", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := array.NewArray(a).Filter(func(x int) bool { return x%2 == 0 }).Value()
if !reflect.DeepEqual(b, []int{2, 4}) {
t.Error("Filter failed. Got", b, "Expected", []int{2, 4})
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Filter(func(x int) bool { return x%2 == 0 })

if !reflect.DeepEqual(b, array.Array[int]{2, 4}) {
t.Error("Filter failed. Got", b, "Expected", array.Array[int]{2, 4})
}

if len(a) == len(b) {
t.Error("Filter failed. Got", len(a), "Expected", len(b))
}
})

t.Run("test Find", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b, _ := array.NewArray(a).Find(func(x int) bool { return x%2 == 0 })
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Find(func(x int) bool { return x%2 == 0 })
if b != 2 {
t.Error("Find failed. Got", b, "Expected", 2)
}
})

t.Run("test Map", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := array.NewArray(a).Map(func(x int) int { return x * 2 }).Value()
if !reflect.DeepEqual(b, []int{2, 4, 6, 8, 10}) {
t.Error("Map failed. Got", b, "Expected", []int{2, 4, 6, 8, 10})
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Map(func(x int) int { return x * 2 })
if b[0] != 2 {
t.Error("Map failed. Got", b, "Expected", array.Array[int]{2, 4, 6, 8, 10})
}
})

t.Run("test flatMap", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := array.NewArray(a).FlatMap(func(x int) []int { return []int{x * 2} }).Value()
if !reflect.DeepEqual(b, []int{2, 4, 6, 8, 10}) {
t.Error("FlatMap failed. Got", b, "Expected", []int{2, 4, 6, 8, 10})
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.FlatMap(func(x int) []int { return []int{x * 2} })

if b[0] != 2 {
t.Error("flatMap failed. Got", b, "Expected", array.Array[int]{2, 4, 6, 8, 10})
}

})

t.Run("test Reduce", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := array.NewArray(a).Reduce(func(x, y int) int { return x + y })
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Reduce(func(x, y int) int { return x + y })
if b != 15 {
t.Error("Reduce failed. Got", b, "Expected", 15)
}
})

t.Run("test Some", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := array.NewArray(a).Some(func(x int) bool { return x%2 == 0 })
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Some(func(x int) bool { return x%2 == 0 })
if !b {
t.Error("Some failed. Got", b, "Expected", true)
}
})

t.Run("test Every", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := array.NewArray(a).Every(func(x int) bool { return x%2 == 0 })
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Every(func(x int) bool { return x%2 == 0 })
if b {
t.Error("Every failed. Got", b, "Expected", false)
}
})

t.Run("test Any", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := array.NewArray(a).Any(func(x int) bool { return x%2 == 0 })
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Any(func(x int) bool { return x%2 == 0 })
if !b {
t.Error("Any failed. Got", b, "Expected", true)
}
})

t.Run("test Length", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := array.NewArray(a).Length()
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Length()
if b != 5 {
t.Error("Length failed. Got", b, "Expected", 5)
}
})

t.Run("test Reverse", func(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := array.NewArray(a).Reverse().Value()
if !reflect.DeepEqual(b, []int{5, 4, 3, 2, 1}) {
t.Error("Reverse failed. Got", b, "Expected", []int{5, 4, 3, 2, 1})
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Reverse()
if !reflect.DeepEqual(b, array.Array[int]{5, 4, 3, 2, 1}) {
t.Error("Reverse failed. Got", b, "Expected", array.Array[int]{5, 4, 3, 2, 1})
}
})

//Shuffle
t.Run("test Shuffle", func(t *testing.T) {
a := array.Array[int]{1, 2, 3, 4, 5}
b := a.Shuffle()
if reflect.DeepEqual(b, array.Array[int]{1, 2, 3, 4, 5}) {
t.Error("Shuffle failed. Got", b, "Expected", array.Array[int]{5, 4, 3, 2, 1})
}
})

Expand All @@ -93,24 +109,47 @@ func TestArray(t *testing.T) {
name string
age int
}
a := []person{
a := array.Array[person]{
{"John", 30},
{"Doe", 25},
{"Jane", 20},
}

b := array.NewArray(a).Sort(func(i, j int) bool { return a[i].age < a[j].age }).Value()
b := a.Sort(func(i, j int) bool { return a[i].age < a[j].age })

if !reflect.DeepEqual(b, []person{
{"Jane", 20},
{"Doe", 25},
{"John", 30},
}) {
t.Error("Sort failed. Got", b, "Expected", []person{
if b[0].age != 20 {
t.Error("Sort failed. Got", b, "Expected", array.Array[person]{
{"Jane", 20},
{"Doe", 25},
{"John", 30},
})
}
})

t.Run("test GroupBy", func(t *testing.T) {

type Itens struct {
Name string
Price float64
Description string
Qty int
}

itens := array.Array[Itens]{
{"Item 1", 10.0, "Description 1", 1},
{"Item 2", 20.0, "Description 2", 2},
{"Item 3", 30.0, "Description 3", 3},
{"Item 4", 40.0, "Description 4", 10},
{"Item 4", 40.0, "Description 4", 15},
{"Item 4", 40.0, "Description 4", 25},
}

grouped := itens.GroupBy(func(item Itens) string {
return fmt.Sprintf("%s - %v", item.Name, item.Price)
})

if len(grouped) != 4 {
t.Error("GroupBy failed. Got", len(grouped), "Expected", 4)
}
})
}
25 changes: 10 additions & 15 deletions array/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,13 @@ import (
"math/rand"
"sort"
"strings"
"time"
)

type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}

/*
* Array functions
* Example:
* a := []int{1, 2, 3, 4, 5}
* b := Filter(a, func(x int) bool { return x%2 == 0 })
* fmt.Println(b) // [2 4]
*/

func Filter[T any](a []T, f func(T) bool) []T {
y := make([]T, len(a))
i := 0
Expand All @@ -31,7 +24,7 @@ func Filter[T any](a []T, f func(T) bool) []T {
return y[:i]
}

//with side effects
// with side effects
func Filter0Loc[T any](a []T, f func(T) bool) []T {
i := 0
for _, x := range a {
Expand All @@ -43,14 +36,14 @@ func Filter0Loc[T any](a []T, f func(T) bool) []T {
return a[:i]
}

func Find[T any](a []T, f func(T) bool) (T, bool) {
func Find[T any](a []T, f func(T) bool) T {
for _, x := range a {
if f(x) {
return x, true
return x
}
}
var zero T
return zero, false
return zero
}

/* Map
Expand All @@ -69,7 +62,7 @@ func Map[T, U any](a []T, f func(T) U) []U {
return b
}

//with side effects
// with side effects
func Map0Loc[T any](a []T, f func(T) T) {
for i, x := range a {
a[i] = f(x)
Expand Down Expand Up @@ -286,9 +279,11 @@ func Reverse[T any](a []T) []T {
* fmt.Println(b) // [2 5 4 3 1]
*/
func Shuffle[T any](a []T) []T {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
b := make([]T, len(a))
for i, x := range rand.Perm(len(a)) {
b[x] = a[i]
perm := r.Perm(len(a))
for i, j := range perm {
b[i] = a[j]
}
return b
}
Expand Down
Loading

0 comments on commit 81a9cf3

Please sign in to comment.