github.com/m4gshm/gollections@v0.0.10/iter/test/api_test.go (about)

     1  package it
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  
    10  	breakLoop "github.com/m4gshm/gollections/break/loop"
    11  	"github.com/m4gshm/gollections/break/predicate"
    12  	"github.com/m4gshm/gollections/convert"
    13  	"github.com/m4gshm/gollections/convert/as"
    14  	"github.com/m4gshm/gollections/iter"
    15  	"github.com/m4gshm/gollections/loop"
    16  	"github.com/m4gshm/gollections/op"
    17  	"github.com/m4gshm/gollections/op/check/not"
    18  	"github.com/m4gshm/gollections/slice"
    19  	sliceIter "github.com/m4gshm/gollections/slice/iter"
    20  	"github.com/m4gshm/gollections/stream"
    21  )
    22  
    23  func Test_FilterAndConvert(t *testing.T) {
    24  
    25  	var (
    26  		toString = func(i int) string { return fmt.Sprintf("%d", i) }
    27  		addTail  = func(s string) string { return s + "_tail" }
    28  	)
    29  	items := []int{1, 2, 3, 4, 5}
    30  	converted := iter.FilterAndConvert(slice.NewIter(items), func(v int) bool { return v%2 == 0 }, convert.And(toString, addTail))
    31  	assert.Equal(t, slice.Of("2_tail", "4_tail"), loop.Slice(converted.Next))
    32  
    33  	converted2 := sliceIter.FilterAndConvert(items, func(v int) bool { return v%2 == 0 }, convert.And(toString, addTail))
    34  	assert.Equal(t, slice.Of("2_tail", "4_tail"), loop.Slice(converted2.Next))
    35  
    36  	//plain old style
    37  	convertedOld := make([]string, 0)
    38  	for _, i := range items {
    39  		if i%2 == 0 {
    40  			convertedOld = append(convertedOld, convert.And(toString, addTail)(i))
    41  		}
    42  	}
    43  
    44  	assert.Equal(t, slice.Of("2_tail", "4_tail"), convertedOld)
    45  }
    46  
    47  func Test_FiltAndConv(t *testing.T) {
    48  	var (
    49  		toString = func(i int) string { return fmt.Sprintf("%d", i) }
    50  		addTail  = func(s string) string { return s + "_tail" }
    51  	)
    52  	items := []int{1, 2, 3, 4, 5}
    53  
    54  	converted := sliceIter.FiltAndConv(items, func(v int) (bool, error) { return v%2 == 0, nil }, wrap(convert.And(toString, addTail)))
    55  	s, _ := breakLoop.Slice(converted.Next)
    56  	assert.Equal(t, slice.Of("2_tail", "4_tail"), s)
    57  }
    58  
    59  func wrap[F, T any](f func(F) T) func(F) (T, error) {
    60  	return func(i F) (T, error) { return f(i), nil }
    61  }
    62  
    63  func Test_FlattSlices(t *testing.T) {
    64  	var (
    65  		odds           = func(v int) bool { return v%2 != 0 }
    66  		multiDimension = [][][]int{{{1, 2, 3}, {4, 5, 6}}, {{7}, nil}, nil}
    67  		expected       = slice.Of(1, 3, 5, 7)
    68  	)
    69  	f := iter.Filter(iter.Flat(iter.Flat(slice.NewIter(multiDimension), as.Is[[][]int]), as.Is[[]int]), odds)
    70  	a := loop.Slice(f.Next)
    71  	assert.Equal(t, expected, a)
    72  
    73  	a = loop.Slice(iter.Filter(iter.Flat(sliceIter.Flat(multiDimension, as.Is[[][]int]), as.Is[[]int]), odds).Next)
    74  	assert.Equal(t, expected, a)
    75  
    76  	//plain old style
    77  	oneDimensionOld := make([]int, 0)
    78  	for _, i := range multiDimension {
    79  		if i == nil {
    80  			continue
    81  		}
    82  		for _, ii := range i {
    83  			if ii == nil {
    84  				continue
    85  			}
    86  			for _, iii := range ii {
    87  				if odds(iii) {
    88  					oneDimensionOld = append(oneDimensionOld, iii)
    89  				}
    90  			}
    91  		}
    92  	}
    93  
    94  	assert.Equal(t, slice.Of(1, 3, 5, 7), oneDimensionOld)
    95  
    96  }
    97  
    98  func Test_ReduceSlices(t *testing.T) {
    99  	var (
   100  		odds           = func(v int) bool { return v%2 != 0 }
   101  		multiDimension = [][][]int{{{1, 2, 3}, {4, 5, 6}}, {{7}, nil}, nil}
   102  	)
   103  
   104  	e := 1 + 3 + 5 + 7
   105  
   106  	oddSum := loop.Reduce(iter.Filter(iter.Flat(iter.Flat(slice.NewIter(multiDimension), as.Is[[][]int]), as.Is[[]int]), odds).Next, op.Sum[int])
   107  	assert.Equal(t, e, oddSum)
   108  
   109  	oddSum = loop.Reduce(iter.Filter(iter.Flat(sliceIter.Flat(multiDimension, as.Is[[][]int]), as.Is[[]int]), odds).Next, op.Sum[int])
   110  	assert.Equal(t, e, oddSum)
   111  
   112  	//plain old style
   113  	oddSum = 0
   114  	for _, i := range multiDimension {
   115  		for _, ii := range i {
   116  			for _, iii := range ii {
   117  				if odds(iii) {
   118  					oddSum += iii
   119  				}
   120  			}
   121  		}
   122  	}
   123  
   124  	assert.Equal(t, e, oddSum)
   125  
   126  }
   127  
   128  type (
   129  	Attributes  struct{ name string }
   130  	Participant struct{ attributes []*Attributes }
   131  )
   132  
   133  func (a *Attributes) GetName() string {
   134  	if a == nil {
   135  		return ""
   136  	}
   137  	return a.name
   138  }
   139  
   140  func (p *Participant) GetAttributes() []*Attributes {
   141  	if p == nil {
   142  		return nil
   143  	}
   144  	return p.attributes
   145  }
   146  
   147  func Test_ConvertFlattStructure_Iterable(t *testing.T) {
   148  	expected := slice.Of("first", "second", "", "third", "")
   149  
   150  	items := []*Participant{{attributes: []*Attributes{{name: "first"}, {name: "second"}, nil}}, nil, {attributes: []*Attributes{{name: "third"}, nil}}}
   151  
   152  	names := loop.Slice(iter.Convert(iter.Flat(slice.NewIter(items), (*Participant).GetAttributes), (*Attributes).GetName).Next)
   153  	assert.Equal(t, expected, names)
   154  
   155  	names = loop.Slice(iter.Convert(sliceIter.Flat(items, (*Participant).GetAttributes), (*Attributes).GetName).Next)
   156  	assert.Equal(t, expected, names)
   157  }
   158  
   159  func Test_ConvertFlatStructure_Iterable(t *testing.T) {
   160  	expected := slice.Of("first", "second", "", "third", "")
   161  
   162  	items := []*Participant{{attributes: []*Attributes{{name: "first"}, {name: "second"}, nil}}, nil, {attributes: []*Attributes{{name: "third"}, nil}}}
   163  
   164  	names, _ := breakLoop.Slice(breakLoop.Convert(sliceIter.Flatt(items, wrapGet((*Participant).GetAttributes)).Next, (*Attributes).GetName).Next)
   165  	assert.Equal(t, expected, names)
   166  }
   167  
   168  func Test_ConvertFilterAndFlattStructure_Iterable(t *testing.T) {
   169  	expected := slice.Of("first", "second", "", "third", "")
   170  
   171  	items := []*Participant{{attributes: []*Attributes{{name: "first"}, {name: "second"}, nil}}, nil, {attributes: []*Attributes{{name: "third"}, nil}}}
   172  
   173  	names := loop.Slice(iter.Convert(iter.FilterAndFlat(slice.NewIter(items), not.Nil[Participant], (*Participant).GetAttributes), (*Attributes).GetName).Next)
   174  	assert.Equal(t, expected, names)
   175  
   176  	names = loop.Slice(iter.Convert(sliceIter.FilterAndFlat(items, not.Nil[Participant], (*Participant).GetAttributes), (*Attributes).GetName).Next)
   177  	assert.Equal(t, expected, names)
   178  }
   179  
   180  func Test_ConvertFiltAndFlattStructure_Iterable(t *testing.T) {
   181  	expected := slice.Of("first", "second", "", "third", "")
   182  
   183  	items := []*Participant{{attributes: []*Attributes{{name: "first"}, {name: "second"}, nil}}, nil, {attributes: []*Attributes{{name: "third"}, nil}}}
   184  	names, _ := breakLoop.Slice(breakLoop.Convert(sliceIter.FiltAndFlat(items, predicate.Wrap(not.Nil[Participant]), wrapGet((*Participant).GetAttributes)).Next, (*Attributes).GetName).Next)
   185  	assert.Equal(t, expected, names)
   186  }
   187  
   188  func wrapGet[S, V any](getter func(S) V) func(S) (V, error) {
   189  	return func(s S) (V, error) {
   190  		return getter(s), nil
   191  	}
   192  }
   193  
   194  func Test_Iterate(t *testing.T) {
   195  	amount := 100
   196  	values := make([]int, amount)
   197  	for i := 0; i < amount; i++ {
   198  		values[i] = i
   199  	}
   200  
   201  	stream := stream.New(sliceIter.New(values).Next)
   202  
   203  	result := make([]int, 0)
   204  
   205  	stream.ForEach(func(i int) { result = append(result, i) })
   206  
   207  	result = make([]int, 0)
   208  	sliceIter.New(values).ForEach(func(i int) { result = append(result, i) })
   209  
   210  	assert.Equal(t, values, result)
   211  
   212  }
   213  
   214  func Test_Group(t *testing.T) {
   215  	groups := iter.Group(iter.Of(0, 1, 1, 2, 4, 3, 1, 6, 7), func(e int) bool { return e%2 == 0 }).Map()
   216  
   217  	assert.Equal(t, len(groups), 2)
   218  	assert.Equal(t, []int{1, 1, 3, 1, 7}, groups[false])
   219  	assert.Equal(t, []int{0, 2, 4, 6}, groups[true])
   220  }
   221  
   222  func Test_ReduceSum(t *testing.T) {
   223  	s := iter.Of(1, 3, 5, 7, 9, 11)
   224  	r := loop.Reduce(s.Next, op.Sum[int])
   225  	assert.Equal(t, 1+3+5+7+9+11, r)
   226  }
   227  
   228  func Test_First(t *testing.T) {
   229  	s := iter.Of(1, 3, 5, 7, 9, 11)
   230  	r, ok := loop.First(s.Next, func(i int) bool { return i > 5 })
   231  	assert.True(t, ok)
   232  	assert.Equal(t, 7, r)
   233  
   234  	_, nook := loop.First(s.Next, func(i int) bool { return i > 12 })
   235  	assert.False(t, nook)
   236  }
   237  
   238  type rows[T any] struct {
   239  	in     []T
   240  	cursor int
   241  }
   242  
   243  func (r *rows[T]) hasNext() bool {
   244  	return r.cursor < len(r.in)
   245  }
   246  
   247  func (r *rows[T]) next() (T, error) {
   248  	e := r.in[r.cursor]
   249  	r.cursor++
   250  	if r.cursor > 3 {
   251  		var no T
   252  		return no, errors.New("next error")
   253  	}
   254  	return e, nil
   255  }
   256  
   257  func Test_OfLoop(t *testing.T) {
   258  	stream := &rows[int]{slice.Of(1, 2, 3), 0}
   259  	iter := breakLoop.New(stream, (*rows[int]).hasNext, (*rows[int]).next)
   260  	s, err := breakLoop.Slice(iter)
   261  
   262  	assert.Equal(t, slice.Of(1, 2, 3), s)
   263  	assert.Nil(t, err)
   264  
   265  	streamWithError := &rows[int]{slice.Of(1, 2, 3, 4), 0}
   266  	iterWithError := breakLoop.New(streamWithError, (*rows[int]).hasNext, (*rows[int]).next)
   267  	s2, err2 := breakLoop.Slice(iterWithError)
   268  
   269  	assert.Equal(t, slice.Of(1, 2, 3), s2)
   270  	assert.Equal(t, "next error", err2.Error())
   271  }