Skip to content

Commit

Permalink
Merge pull request #3 from geniussportsgroup/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
lrleon committed Mar 21, 2021
2 parents eb9ed9a + 64fa35b commit f64f068
Show file tree
Hide file tree
Showing 2 changed files with 212 additions and 2 deletions.
143 changes: 141 additions & 2 deletions functional.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package FunctionalLib

import Seq "github.com/geniussportsgroup/Slist"
import (
Seq "github.com/geniussportsgroup/Slist"
)

type SequentialIterator interface {
ResetFirst() interface{}
Expand All @@ -22,11 +24,103 @@ type Pair struct {
Item1, Item2 interface{}
}

type Tuple struct {
l *[]interface{}
}

func NewTuple(items ...interface{}) *Tuple {

s := make([]interface{}, 0, len(items))
tuple := Tuple{l: &s}
for _, i := range items {
*tuple.l = append(*tuple.l, i)
}
return &tuple
}

func BuildTuple(n int) *Tuple {
s := make([]interface{}, n, n)
return &Tuple{l: &s}
}

func (tuple *Tuple) Set(i int, item interface{}) {
(*tuple.l)[i] = item
}

func (tuple *Tuple) Traverse(f func(interface{}) bool) bool {
ptr := tuple.l
for i := 0; i < len(*tuple.l); i++ {
if !f((*ptr)[i]) {
return false
}
}
return true
}

func (tuple *Tuple) Append(item interface{}, items ...interface{}) interface{} {
*tuple.l = append(*tuple.l, item)
for _, i := range items {
*tuple.l = append(*tuple.l, i)
}
return tuple
}

func (tuple *Tuple) Size() int {
return len(*tuple.l)
}

func (tuple *Tuple) Swap(other interface{}) interface{} {
otherTuple := other.(*Tuple)
tuple.l, otherTuple.l = otherTuple.l, tuple.l
return tuple
}

func (tuple *Tuple) IsEmpty() bool {
return tuple.Size() == 0
}

type TupleIterator struct {
tuple *Tuple
pos int
}

func (tuple *Tuple) CreateIterator() interface{} {
return &TupleIterator{
tuple: tuple,
pos: 0,
}
}

func NewTupleIterator(tuple Tuple) *TupleIterator {
return tuple.CreateIterator().(*TupleIterator)
}

func (it *TupleIterator) HasCurr() bool {
return it.pos < len(*it.tuple.l)
}

func (it *TupleIterator) GetCurr() interface{} {
return (*it.tuple.l)[it.pos]
}

func (tuple *Tuple) Nth(i int) interface{} {
return (*tuple.l)[i]
}

func (it *TupleIterator) Next() interface{} {
it.pos++
return it
}

func (it *TupleIterator) ResetFirst() interface{} {
it.pos = 0
return it
}

// Execute operation receiving every item of the sequence. Return seq
func ForEach(seq Sequence, operation func(interface{})) interface{} {

seq.Traverse(func(i interface{}) bool {

operation(i)
return true
})
Expand Down Expand Up @@ -217,3 +311,48 @@ func Position(seq Sequence, predicate func(item interface{}) bool) int {

return -1
}

// Zip all the lists into a list of tuples
func TZip(list *Seq.Slist, lists ...*Seq.Slist) *Seq.Slist {

sz := len(lists) + 1
ret := Seq.New()

for it := Seq.NewIterator(list); it.HasCurr(); it.Next() {
tuple := BuildTuple(sz)
tuple.Set(0, it.GetCurr())
ret.Append(tuple)
}

for i, l := range lists {

zipL := Zip(ret, l)
for it := Seq.NewIterator(zipL); it.HasCurr(); it.Next() { // traverse i-th list
pair := it.GetCurr().(Pair)
tuple := pair.Item1.(*Tuple)
item := pair.Item2
tuple.Set(i+1, item)
}
}

return ret
}

// Unzip a list of tuples into a tuple of lists
func TUnzip(tupleList *Seq.Slist) *Tuple {

tupleSize := tupleList.First().(*Tuple).Size()
result := BuildTuple(tupleSize)
for i := 0; i < tupleSize; i++ {
result.Set(i, Seq.New())
}

for it := Seq.NewIterator(tupleList); it.HasCurr(); it.Next() {
tuple := it.GetCurr().(*Tuple)
for i := 0; i < tuple.Size(); i++ {
result.Nth(i).(*Seq.Slist).Append(tuple.Nth(i))
}
}

return result
}
71 changes: 71 additions & 0 deletions functional_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,74 @@ func TestPosition(t *testing.T) {
}), i)
}
}

func TestNewTuple(t *testing.T) {

tuple4 := NewTuple(1, 2, 3, 4)
assert.Equal(t, tuple4.Size(), 4)
assert.Equal(t, tuple4.Nth(0).(int), 1)
}

func TestTZip(t *testing.T) {

l1 := Seq.New(1, 2, 3, 4, 5)
l2 := Seq.New("A", "B", "C", "D", "E")
l3 := Seq.New(-5, -4, -3, -2, -1)

zl := TZip(l1, l2, l3)

assert.Equal(t, zl.Size(), l1.Size())

assert.True(t, All(Zip(zl, l1), func(item interface{}) bool {
pair := item.(Pair)
tuple := pair.Item1.(*Tuple)
i := pair.Item2.(int)
return tuple.Nth(0) == i
}))

assert.True(t, All(Zip(zl, l2), func(item interface{}) bool {
pair := item.(Pair)
tuple := pair.Item1.(*Tuple)
str := pair.Item2.(string)
return tuple.Nth(1) == str
}))

assert.True(t, All(Zip(zl, l3), func(item interface{}) bool {
pair := item.(Pair)
tuple := pair.Item1.(*Tuple)
i := pair.Item2.(int)
return tuple.Nth(2) == i
}))
}

func TestTUnzip(t *testing.T) {

l1 := Seq.New(1, 2, 3, 4, 5)
l2 := Seq.New("A", "B", "C", "D", "E")
l3 := Seq.New(-5, -4, -3, -2, -1)

zl := TZip(l1, l2, l3)

tuple := TUnzip(zl)

assert.True(t, All(Zip(tuple.Nth(0).(*Seq.Slist), l1), func(p interface{}) bool {
pair := p.(Pair)
i1 := pair.Item1.(int)
i2 := pair.Item2.(int)
return i1 == i2
}))

assert.True(t, All(Zip(tuple.Nth(1).(*Seq.Slist), l2), func(p interface{}) bool {
pair := p.(Pair)
i1 := pair.Item1.(string)
i2 := pair.Item2.(string)
return i1 == i2
}))

assert.True(t, All(Zip(tuple.Nth(2).(*Seq.Slist), l3), func(p interface{}) bool {
pair := p.(Pair)
i1 := pair.Item1.(int)
i2 := pair.Item2.(int)
return i1 == i2
}))
}

0 comments on commit f64f068

Please sign in to comment.