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 }