• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

enetx / g / 16786172903

06 Aug 2025 07:07PM UTC coverage: 85.592% (-0.01%) from 85.604%
16786172903

push

github

enetx
RangeInclusive

8 of 10 new or added lines in 1 file covered. (80.0%)

1 existing line in 1 file now uncovered.

3885 of 4539 relevant lines covered (85.59%)

108.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.77
/slice_iter.go
1
package g
2

3
import (
4
        "context"
5
        "iter"
6
        "reflect"
7
        "runtime"
8

9
        "github.com/enetx/g/cmp"
10
        "github.com/enetx/g/constraints"
11
        "github.com/enetx/g/f"
12
)
13

14
// Range returns a SeqSlice[T] yielding a sequence of integers of type T,
15
// starting at start, incrementing by step, and ending before stop (exclusive).
16
//
17
//   - If step is omitted, it defaults to 1.
18
//   - If step is 0, the sequence is empty.
19
//   - If step does not move toward stop (e.g., positive step with start > stop),
20
//     the sequence is empty.
21
//
22
// Examples:
23
//   - Range(0, 5) yields [0, 1, 2, 3, 4]
24
//   - Range(5, 0, -1) yields [5, 4, 3, 2, 1]
25
func Range[T constraints.Integer](start, stop T, step ...T) SeqSlice[T] {
7✔
26
        st := Slice[T](step).Get(0).UnwrapOr(1)
7✔
27

7✔
28
        if st == 0 {
8✔
29
                return func(func(T) bool) {}
2✔
30
        }
31

32
        return func(yield func(T) bool) {
12✔
33
                for i := start; (st > 0 && i < stop) || (st < 0 && i > stop); i += st {
23✔
34
                        if !yield(i) {
17✔
35
                                return
×
36
                        }
×
37
                }
38
        }
39
}
40

41
// RangeInclusive returns a SeqSlice[T] yielding a sequence of integers of type T,
42
// starting at start, incrementing by step, and ending at stop (inclusive).
43
//
44
//   - If step is omitted, it defaults to 1.
45
//   - If step is 0, the sequence is empty.
46
//   - If step does not move toward stop (e.g., positive step with start > stop),
47
//     the sequence is empty.
48
//
49
// Examples:
50
//   - RangeInclusive(0, 5) yields [0, 1, 2, 3, 4, 5]
51
//   - RangeInclusive(5, 0, -1) yields [5, 4, 3, 2, 1, 0]
52
func RangeInclusive[T constraints.Integer](start, stop T, step ...T) SeqSlice[T] {
9✔
53
        st := Slice[T](step).Get(0).UnwrapOr(1)
9✔
54

9✔
55
        if st == 0 {
10✔
56
                return func(func(T) bool) {}
2✔
57
        }
58

59
        return func(yield func(T) bool) {
16✔
60
                for i := start; (st > 0 && i <= stop) || (st < 0 && i >= stop); i += st {
34✔
61
                        if !yield(i) {
26✔
NEW
62
                                return
×
NEW
63
                        }
×
64
                }
65
        }
66
}
67

68
// Parallel runs this SeqSlice in parallel using the given number of workers.
69
func (seq SeqSlice[V]) Parallel(workers ...Int) SeqSlicePar[V] {
17✔
70
        numCPU := Int(runtime.NumCPU())
17✔
71
        count := Slice[Int](workers).Get(0).UnwrapOr(numCPU)
17✔
72

17✔
73
        if count.Lte(0) {
17✔
74
                count = numCPU
×
75
        }
×
76

77
        return SeqSlicePar[V]{
17✔
78
                seq:     seq,
17✔
79
                workers: count,
17✔
80
                process: func(v V) (V, bool) { return v, true },
97✔
81
        }
82
}
83

84
// Pull converts the “push-style” iterator sequence seq
85
// into a “pull-style” iterator accessed by the two functions
86
// next and stop.
87
//
88
// Next returns the next value in the sequence
89
// and a boolean indicating whether the value is valid.
90
// When the sequence is over, next returns the zero V and false.
91
// It is valid to call next after reaching the end of the sequence
92
// or after calling stop. These calls will continue
93
// to return the zero V and false.
94
//
95
// Stop ends the iteration. It must be called when the caller is
96
// no longer interested in next values and next has not yet
97
// signaled that the sequence is over (with a false boolean return).
98
// It is valid to call stop multiple times and when next has
99
// already returned false.
100
//
101
// It is an error to call next or stop from multiple goroutines
102
// simultaneously.
103
func (seq SeqSlice[V]) Pull() (func() (V, bool), func()) { return iter.Pull(iter.Seq[V](seq)) }
4✔
104

105
// All checks whether all elements in the iterator satisfy the provided condition.
106
// This function is useful when you want to determine if all elements in an iterator
107
// meet a specific criteria.
108
//
109
// Parameters:
110
// - fn func(V) bool: A function that returns a boolean indicating whether the element satisfies
111
// the condition.
112
//
113
// Returns:
114
// - bool: True if all elements in the iterator satisfy the condition, false otherwise.
115
//
116
// Example usage:
117
//
118
//        slice := g.SliceOf(1, 2, 3, 4, 5, 6, 7, -1, -2)
119
//        isPositive := func(num int) bool { return num > 0 }
120
//        allPositive := slice.Iter().All(isPositive)
121
//
122
// The resulting allPositive will be true if all elements returned by the iterator are positive.
123
func (seq SeqSlice[V]) All(fn func(v V) bool) bool {
19✔
124
        for v := range seq {
46✔
125
                if !fn(v) {
36✔
126
                        return false
9✔
127
                }
9✔
128
        }
129

130
        return true
10✔
131
}
132

133
// Any checks whether any element in the iterator satisfies the provided condition.
134
// This function is useful when you want to determine if at least one element in an iterator
135
// meets a specific criteria.
136
//
137
// Parameters:
138
// - fn func(V) bool: A function that returns a boolean indicating whether the element satisfies
139
// the condition.
140
//
141
// Returns:
142
// - bool: True if at least one element in the iterator satisfies the condition, false otherwise.
143
//
144
// Example usage:
145
//
146
//        slice := g.Slice[int]{1, 3, 5, 7, 9}
147
//        isEven := func(num int) bool { return num%2 == 0 }
148
//        anyEven := slice.Iter().Any(isEven)
149
//
150
// The resulting anyEven will be true if at least one element returned by the iterator is even.
151
func (seq SeqSlice[V]) Any(fn func(V) bool) bool {
28✔
152
        for v := range seq {
67✔
153
                if fn(v) {
53✔
154
                        return true
14✔
155
                }
14✔
156
        }
157

158
        return false
14✔
159
}
160

161
// Chain concatenates the current iterator with other iterators, returning a new iterator.
162
//
163
// The function creates a new iterator that combines the elements of the current iterator
164
// with elements from the provided iterators in the order they are given.
165
//
166
// Params:
167
//
168
// - seqs ([]SeqSlice[V]): Other iterators to be concatenated with the current iterator.
169
//
170
// Returns:
171
//
172
// - sequence[V]: A new iterator containing elements from the current iterator and the provided iterators.
173
//
174
// Example usage:
175
//
176
//        iter1 := g.Slice[int]{1, 2, 3}.Iter()
177
//        iter2 := g.Slice[int]{4, 5, 6}.Iter()
178
//        iter1.Chain(iter2).Collect().Print()
179
//
180
// Output: [1, 2, 3, 4, 5, 6]
181
//
182
// The resulting iterator will contain elements from both iterators in the specified order.
183
func (seq SeqSlice[V]) Chain(seqs ...SeqSlice[V]) SeqSlice[V] {
2✔
184
        return func(yield func(V) bool) {
4✔
185
                for _, seq := range append([]SeqSlice[V]{seq}, seqs...) {
6✔
186
                        seq(func(v V) bool {
12✔
187
                                return yield(v)
8✔
188
                        })
8✔
189
                }
190
        }
191
}
192

193
// Chunks returns an iterator that yields chunks of elements of the specified size.
194
//
195
// The function creates a new iterator that yields chunks of elements from the original iterator,
196
// with each chunk containing elements of the specified size.
197
//
198
// Params:
199
//
200
// - n (Int): The size of each chunk.
201
//
202
// Returns:
203
//
204
// - SeqSlices[V]: An iterator yielding chunks of elements of the specified size.
205
//
206
// Example usage:
207
//
208
//        slice := g.Slice[int]{1, 2, 3, 4, 5, 6}
209
//        chunks := slice.Iter().Chunks(2).Collect()
210
//
211
// Output: [Slice[1, 2] Slice[3, 4] Slice[5, 6]]
212
//
213
// The resulting iterator will yield chunks of elements, each containing the specified number of elements.
214
func (seq SeqSlice[V]) Chunks(n Int) SeqSlices[V] {
5✔
215
        return func(yield func([]V) bool) {
10✔
216
                if n <= 0 {
5✔
217
                        return
×
218
                }
×
219

220
                buf := make([]V, 0, n)
5✔
221

5✔
222
                seq(func(v V) bool {
23✔
223
                        buf = append(buf, v)
18✔
224
                        if len(buf) == int(n) {
24✔
225
                                chunk := make([]V, n)
6✔
226
                                copy(chunk, buf)
6✔
227
                                if !yield(chunk) {
6✔
228
                                        return false
×
229
                                }
×
230
                                buf = buf[:0]
6✔
231
                        }
232
                        return true
18✔
233
                })
234

235
                if len(buf) > 0 {
7✔
236
                        chunk := make([]V, len(buf))
2✔
237
                        copy(chunk, buf)
2✔
238
                        yield(chunk)
2✔
239
                }
2✔
240
        }
241
}
242

243
// Collect gathers all elements from the iterator into a Slice.
244
func (seq SeqSlice[V]) Collect() Slice[V] {
271✔
245
        collection := make([]V, 0)
271✔
246

271✔
247
        seq(func(v V) bool {
1,008✔
248
                collection = append(collection, v)
737✔
249
                return true
737✔
250
        })
737✔
251

252
        return collection
271✔
253
}
254

255
// Collect gathers all elements from the iterator into a []Slice.
256
func (seqs SeqSlices[V]) Collect() []Slice[V] {
16✔
257
        collection := make([]Slice[V], 0)
16✔
258

16✔
259
        seqs(func(v []V) bool {
77✔
260
                inner := seqSlice(v).Collect()
61✔
261
                collection = append(collection, inner)
61✔
262
                return true
61✔
263
        })
61✔
264

265
        return collection
16✔
266
}
267

268
// Count consumes the iterator, counting the number of iterations and returning it.
269
func (seq SeqSlice[V]) Count() Int {
2✔
270
        var counter Int
2✔
271
        seq(func(V) bool {
7✔
272
                counter++
5✔
273
                return true
5✔
274
        })
5✔
275

276
        return counter
2✔
277
}
278

279
// Counter returns a SeqMapOrd[V, Int] with the counts of each unique element in the slice.
280
// This function is useful when you want to count the occurrences of each unique element in a slice.
281
//
282
// Returns:
283
//
284
// - SeqMapOrd[V, Int]: with keys representing the unique elements in the slice
285
// and values representing the counts of those elements.
286
//
287
// Example usage:
288
//
289
//        slice := g.Slice[int]{1, 2, 3, 1, 2, 1}
290
//        counts := slice.Iter().Counter().Collect()
291
//        // The counts ordered Map will contain:
292
//        // 1 -> 3 (since 1 appears three times)
293
//        // 2 -> 2 (since 2 appears two times)
294
//        // 3 -> 1 (since 3 appears once)
295
func (seq SeqSlice[V]) Counter() SeqMapOrd[V, Int] {
2✔
296
        result := NewMapOrd[V, Int]()
2✔
297

2✔
298
        seq(func(v V) bool {
18✔
299
                r := result.Get(v).UnwrapOrDefault()
16✔
300
                r++
16✔
301
                result.Set(v, r)
16✔
302
                return true
16✔
303
        })
16✔
304

305
        return result.Iter()
2✔
306
}
307

308
// Combinations generates all combinations of length 'n' from the sequence.
309
func (seq SeqSlice[V]) Combinations(size Int) SeqSlices[V] {
5✔
310
        return func(yield func([]V) bool) {
10✔
311
                k := int(size)
5✔
312
                s := seq.Collect()
5✔
313
                n := len(s)
5✔
314

5✔
315
                if k > n || k <= 0 {
7✔
316
                        return
2✔
317
                }
2✔
318

319
                indices := make([]int, k)
3✔
320
                for i := range k {
10✔
321
                        indices[i] = i
7✔
322
                }
7✔
323

324
                buf := make([]V, k)
3✔
325

3✔
326
                for {
19✔
327
                        for i, idx := range indices {
52✔
328
                                buf[i] = s[idx]
36✔
329
                        }
36✔
330

331
                        chunk := make([]V, k)
16✔
332
                        copy(chunk, buf)
16✔
333
                        if !yield(chunk) {
16✔
334
                                return
×
335
                        }
×
336

337
                        i := k - 1
16✔
338
                        for i >= 0 && indices[i] == n-k+i {
30✔
339
                                i--
14✔
340
                        }
14✔
341
                        if i < 0 {
19✔
342
                                return
3✔
343
                        }
3✔
344

345
                        indices[i]++
13✔
346
                        for j := i + 1; j < k; j++ {
20✔
347
                                indices[j] = indices[j-1] + 1
7✔
348
                        }
7✔
349
                }
350
        }
351
}
352

353
// Cycle returns an iterator that endlessly repeats the elements of the current sequence.
354
func (seq SeqSlice[V]) Cycle() SeqSlice[V] {
1✔
355
        return func(yield func(V) bool) {
2✔
356
                for {
5✔
357
                        cont := true
4✔
358
                        seq(func(v V) bool {
14✔
359
                                cont = cont && yield(v)
10✔
360
                                return cont
10✔
361
                        })
10✔
362
                        if !cont {
5✔
363
                                return
1✔
364
                        }
1✔
365
                }
366
        }
367
}
368

369
// Enumerate adds an index to each element in the iterator.
370
//
371
// Returns:
372
//
373
// - SeqMapOrd[Int, V] An iterator with each element of type Pair[Int, V], where the first
374
// element of the pair is the index and the second element is the original element from the
375
// iterator.
376
//
377
// Example usage:
378
//
379
//        ps := g.SliceOf[g.String]("bbb", "ddd", "xxx", "aaa", "ccc").
380
//                Iter().
381
//                Enumerate().
382
//                Collect()
383
//
384
//        ps.Print()
385
//
386
// Output: MapOrd{0:bbb, 1:ddd, 2:xxx, 3:aaa, 4:ccc}
387
func (seq SeqSlice[V]) Enumerate() SeqMapOrd[Int, V] {
1✔
388
        return func(yield func(Int, V) bool) {
2✔
389
                i := Int(-1)
1✔
390
                seq(func(v V) bool {
6✔
391
                        i++
5✔
392
                        return yield(i, v)
5✔
393
                })
5✔
394
        }
395
}
396

397
// Dedup creates a new iterator that removes consecutive duplicate elements from the original iterator,
398
// leaving only one occurrence of each unique element. If the iterator is sorted, all elements will be unique.
399
//
400
// Parameters:
401
// - None
402
//
403
// Returns:
404
// - SeqSlice[V]: A new iterator with consecutive duplicates removed.
405
//
406
// Example usage:
407
//
408
//        slice := g.Slice[int]{1, 2, 2, 3, 4, 4, 4, 5}
409
//        iter := slice.Iter().Dedup()
410
//        result := iter.Collect()
411
//        result.Print()
412
//
413
// Output: [1 2 3 4 5]
414
//
415
// The resulting iterator will contain only unique elements, removing consecutive duplicates.
416
func (seq SeqSlice[V]) Dedup() SeqSlice[V] {
4✔
417
        var current V
4✔
418
        comparable := f.IsComparable(current)
4✔
419

4✔
420
        return func(yield func(V) bool) {
8✔
421
                seq(func(v V) bool {
32✔
422
                        if comparable {
50✔
423
                                if f.Eq[any](current)(v) {
30✔
424
                                        return true
8✔
425
                                }
8✔
426
                        } else {
6✔
427
                                if f.Eqd(current)(v) {
8✔
428
                                        return true
2✔
429
                                }
2✔
430
                        }
431

432
                        current = v
18✔
433
                        return yield(v)
18✔
434
                })
435
        }
436
}
437

438
// Filter returns a new iterator containing only the elements that satisfy the provided function.
439
//
440
// The function applies the provided function to each element of the iterator.
441
// If the function returns true for an element, that element is included in the resulting iterator.
442
//
443
// Parameters:
444
//
445
// - fn (func(V) bool): The function to be applied to each element of the iterator
446
// to determine if it should be included in the result.
447
//
448
// Returns:
449
//
450
// - SeqSlice[V]: A new iterator containing the elements that satisfy the given condition.
451
//
452
// Example usage:
453
//
454
//        slice := g.Slice[int]{1, 2, 3, 4, 5}
455
//        even := slice.Iter().
456
//                Filter(
457
//                        func(val int) bool {
458
//                                return val%2 == 0
459
//                        }).
460
//                Collect()
461
//        even.Print()
462
//
463
// Output: [2 4].
464
//
465
// The resulting iterator will contain only the elements that satisfy the provided function.
466
func (seq SeqSlice[V]) Filter(fn func(V) bool) SeqSlice[V] { return filterSlice(seq, fn) }
1✔
467

468
func filterSlice[V any](seq SeqSlice[V], fn func(V) bool) SeqSlice[V] {
58✔
469
        return func(yield func(V) bool) {
116✔
470
                seq(func(v V) bool {
177✔
471
                        if fn(v) {
228✔
472
                                return yield(v)
109✔
473
                        }
109✔
474
                        return true
10✔
475
                })
476
        }
477
}
478

479
// Exclude returns a new iterator excluding elements that satisfy the provided function.
480
//
481
// The function applies the provided function to each element of the iterator.
482
// If the function returns true for an element, that element is excluded from the resulting iterator.
483
//
484
// Parameters:
485
//
486
// - fn (func(V) bool): The function to be applied to each element of the iterator
487
// to determine if it should be excluded from the result.
488
//
489
// Returns:
490
//
491
// - SeqSlice[V]: A new iterator containing the elements that do not satisfy the given condition.
492
//
493
// Example usage:
494
//
495
//        slice := g.Slice[int]{1, 2, 3, 4, 5}
496
//        notEven := slice.Iter().
497
//                Exclude(
498
//                        func(val int) bool {
499
//                                return val%2 == 0
500
//                        }).
501
//                Collect()
502
//        notEven.Print()
503
//
504
// Output: [1, 3, 5]
505
//
506
// The resulting iterator will contain only the elements that do not satisfy the provided function.
507
func (seq SeqSlice[V]) Exclude(fn func(V) bool) SeqSlice[V] {
57✔
508
        return filterSlice(seq, func(v V) bool { return !fn(v) })
171✔
509
}
510

511
// Fold accumulates values in the iterator using a function.
512
//
513
// The function iterates through the elements of the iterator, accumulating values
514
// using the provided function and an initial value.
515
//
516
// Params:
517
//
518
//   - init (V): The initial value for accumulation.
519
//   - fn (func(V, V) V): The function that accumulates values; it takes two arguments
520
//     of type V and returns a value of type V.
521
//
522
// Returns:
523
//
524
// - T: The accumulated value after applying the function to all elements.
525
//
526
// Example usage:
527
//
528
//        slice := g.Slice[int]{1, 2, 3, 4, 5}
529
//        sum := slice.Iter().
530
//                Fold(0,
531
//                        func(acc, val int) int {
532
//                                return acc + val
533
//                        })
534
//        fmt.Println(sum)
535
//
536
// Output: 15.
537
//
538
// The resulting value will be the accumulation of elements based on the provided function.
539
func (seq SeqSlice[V]) Fold(init V, fn func(acc, val V) V) V {
1✔
540
        seq(func(v V) bool {
6✔
541
                init = fn(init, v)
5✔
542
                return true
5✔
543
        })
5✔
544
        return init
1✔
545
}
546

547
// ForEach iterates through all elements and applies the given function to each.
548
//
549
// The function applies the provided function to each element of the iterator.
550
//
551
// Params:
552
//
553
// - fn (func(V)): The function to apply to each element.
554
//
555
// Example usage:
556
//
557
//        iter := g.Slice[int]{1, 2, 3, 4, 5}.Iter()
558
//        iter.ForEach(func(val V) {
559
//            fmt.Println(val) // Replace this with the function logic you need.
560
//        })
561
//
562
// The provided function will be applied to each element in the iterator.
563
func (seq SeqSlice[V]) ForEach(fn func(v V)) {
63✔
564
        seq(func(v V) bool {
183✔
565
                fn(v)
120✔
566
                return true
120✔
567
        })
120✔
568
}
569

570
// Flatten flattens an iterator of iterators into a single iterator.
571
//
572
// The function creates a new iterator that flattens a sequence of iterators,
573
// returning a single iterator containing elements from each iterator in sequence.
574
//
575
// Returns:
576
//
577
// - SeqSlice[V]: A single iterator containing elements from the sequence of iterators.
578
//
579
// Example usage:
580
//
581
//        nestedSlice := g.Slice[any]{
582
//                1,
583
//                g.SliceOf(2, 3),
584
//                "abc",
585
//                g.SliceOf("def", "ghi"),
586
//                g.SliceOf(4.5, 6.7),
587
//        }
588
//
589
//        nestedSlice.Iter().Flatten().Collect().Print()
590
//
591
// Output: Slice[1, 2, 3, abc, def, ghi, 4.5, 6.7]
592
//
593
// The resulting iterator will contain elements from each iterator in sequence.
594
func (seq SeqSlice[V]) Flatten() SeqSlice[V] {
3✔
595
        return func(yield func(V) bool) {
6✔
596
                var flatten func(item any) bool
3✔
597
                flatten = func(item any) bool {
17✔
598
                        rv := reflect.ValueOf(item)
14✔
599
                        switch rv.Kind() {
14✔
600
                        case reflect.Slice, reflect.Array:
3✔
601
                                for i := range rv.Len() {
9✔
602
                                        if !flatten(rv.Index(i).Interface()) {
6✔
603
                                                return false
×
604
                                        }
×
605
                                }
606
                        default:
11✔
607
                                if v, ok := item.(V); ok {
22✔
608
                                        if !yield(v) {
11✔
609
                                                return false
×
610
                                        }
×
611
                                }
612
                        }
613
                        return true
14✔
614
                }
615

616
                seq(func(item V) bool {
11✔
617
                        return flatten(item)
8✔
618
                })
8✔
619
        }
620
}
621

622
// Inspect creates a new iterator that wraps around the current iterator
623
// and allows inspecting each element as it passes through.
624
func (seq SeqSlice[V]) Inspect(fn func(v V)) SeqSlice[V] {
1✔
625
        return func(yield func(V) bool) {
2✔
626
                seq(func(v V) bool {
4✔
627
                        fn(v)
3✔
628
                        return yield(v)
3✔
629
                })
3✔
630
        }
631
}
632

633
// Intersperse inserts the provided separator between elements of the iterator.
634
//
635
// The function creates a new iterator that inserts the given separator between each
636
// consecutive pair of elements in the original iterator.
637
//
638
// Params:
639
//
640
// - sep (V): The separator to intersperse between elements.
641
//
642
// Returns:
643
//
644
// - SeqSlice[V]: An iterator containing elements with the separator interspersed.
645
//
646
// Example usage:
647
//
648
//        g.Slice[string]{"Hello", "World", "!"}.
649
//                Iter().
650
//                Intersperse(" ").
651
//                Collect().
652
//                Join().
653
//                Print()
654
//
655
// Output: "Hello World !".
656
//
657
// The resulting iterator will contain elements with the separator interspersed.
658
func (seq SeqSlice[V]) Intersperse(sep V) SeqSlice[V] {
6✔
659
        return func(yield func(V) bool) {
12✔
660
                first := true
6✔
661

6✔
662
                seq(func(v V) bool {
18✔
663
                        if !first && !yield(sep) {
12✔
664
                                return false
×
665
                        }
×
666

667
                        first = false
12✔
668
                        return yield(v)
12✔
669
                })
670
        }
671
}
672

673
// Map transforms each element in the iterator using the given function.
674
//
675
// The function creates a new iterator by applying the provided function to each element
676
// of the original iterator.
677
//
678
// Params:
679
//
680
// - fn (func(V) V): The function used to transform elements.
681
//
682
// Returns:
683
//
684
// - SeqSlice[V]: A iterator containing elements transformed by the provided function.
685
//
686
// Example usage:
687
//
688
//        slice := g.Slice[int]{1, 2, 3}
689
//        doubled := slice.
690
//                Iter().
691
//                Map(
692
//                        func(val int) int {
693
//                                return val * 2
694
//                        }).
695
//                Collect()
696
//        doubled.Print()
697
//
698
// Output: [2 4 6].
699
//
700
// The resulting iterator will contain elements transformed by the provided function.
701
func (seq SeqSlice[V]) Map(transform func(V) V) SeqSlice[V] { return transformSeqSlice(seq, transform) }
5✔
702

703
// reduceSeqSlices transforms a SeqSlices[V] into a SeqSlice[U] by applying a function `fn`
704
// to each slice ([]V) and producing a single value of type U for each.
705
// It is useful when you want to reduce or map entire sub-slices (e.g., [][]byte → []Bytes).
706
func reduceSeqSlices[V, U any, S ~[]V](seq SeqSlices[V], fn func(S) U) SeqSlice[U] {
×
707
        return func(yield func(U) bool) {
×
708
                seq(func(sl []V) bool {
×
709
                        return yield(fn(S(sl)))
×
710
                })
×
711
        }
712
}
713

714
// transformSeqSlice applies a transformation function to each element of a SeqSlice[V],
715
// producing a SeqSlice[U]. This is equivalent to mapping over a sequence.
716
func transformSeqSlice[V, U any](seq SeqSlice[V], fn func(V) U) SeqSlice[U] {
54✔
717
        return func(yield func(U) bool) {
108✔
718
                seq(func(v V) bool {
169✔
719
                        return yield(fn(v))
115✔
720
                })
115✔
721
        }
722
}
723

724
// transformSeq converts a generic iter.Seq[V] into a SeqSlice[U] by mapping each element
725
// with the provided transformation function `fn`.
726
func transformSeq[V, U any](seq iter.Seq[V], fn func(V) U) SeqSlice[U] {
135✔
727
        return func(yield func(U) bool) {
270✔
728
                seq(func(v V) bool {
459✔
729
                        return yield(fn(v))
324✔
730
                })
324✔
731
        }
732
}
733

734
// Partition divides the elements of the iterator into two separate slices based on a given predicate function.
735
//
736
// The function takes a predicate function 'fn', which should return true or false for each element in the iterator.
737
// Elements for which 'fn' returns true are collected into the left slice, while those for which 'fn' returns false
738
// are collected into the right slice.
739
//
740
// Params:
741
//
742
// - fn (func(V) bool): The predicate function used to determine the placement of elements.
743
//
744
// Returns:
745
//
746
// - (Slice[V], Slice[V]): Two slices representing elements that satisfy and don't satisfy the predicate, respectively.
747
//
748
// Example usage:
749
//
750
//        evens, odds := g.Slice[int]{1, 2, 3, 4, 5}.
751
//                Iter().
752
//                Partition(
753
//                        func(v int) bool {
754
//                                return v%2 == 0
755
//                        })
756
//
757
//        fmt.Println("Even numbers:", evens) // Output: Even numbers: Slice[2, 4]
758
//        fmt.Println("Odd numbers:", odds)   // Output: Odd numbers: Slice[1, 3, 5]
759
//
760
// The resulting two slices will contain elements separated based on whether they satisfy the predicate or not.
761
func (seq SeqSlice[V]) Partition(fn func(v V) bool) (Slice[V], Slice[V]) {
3✔
762
        left, right := make([]V, 0), make([]V, 0)
3✔
763
        seq(func(v V) bool {
12✔
764
                if fn(v) {
14✔
765
                        left = append(left, v)
5✔
766
                } else {
9✔
767
                        right = append(right, v)
4✔
768
                }
4✔
769
                return true
9✔
770
        })
771

772
        return left, right
3✔
773
}
774

775
// Permutations generates iterators of all permutations of elements.
776
//
777
// The function uses a recursive approach to generate all the permutations of the elements.
778
// If the iterator is empty or contains a single element, it returns the iterator itself
779
// wrapped in a single-element iterator.
780
//
781
// Returns:
782
//
783
// - SeqSlices[V]: An iterator of iterators containing all possible permutations of the
784
// elements in the iterator.
785
//
786
// Example usage:
787
//
788
//        slice := g.Slice[int]{1, 2, 3}
789
//        perms := slice.Iter().Permutations().Collect()
790
//        for _, perm := range perms {
791
//            fmt.Println(perm)
792
//        }
793
//
794
// Output:
795
//
796
//        Slice[1, 2, 3]
797
//        Slice[1, 3, 2]
798
//        Slice[2, 1, 3]
799
//        Slice[2, 3, 1]
800
//        Slice[3, 1, 2]
801
//        Slice[3, 2, 1]
802
//
803
// The resulting iterator will contain iterators representing all possible permutations
804
// of the elements in the original iterator.
805
func (seq SeqSlice[V]) Permutations() SeqSlices[V] {
5✔
806
        return func(yield func([]V) bool) {
10✔
807
                s := seq.Collect()
5✔
808
                n := len(s)
5✔
809
                if n == 0 {
6✔
810
                        return
1✔
811
                }
1✔
812

813
                indices := make([]int, n)
4✔
814
                for i := range indices {
14✔
815
                        indices[i] = i
10✔
816
                }
10✔
817

818
                buf := make([]V, n)
4✔
819

4✔
820
                for {
37✔
821
                        for i, v := range indices {
152✔
822
                                buf[i] = s[v]
119✔
823
                        }
119✔
824

825
                        chunk := make([]V, n)
33✔
826
                        copy(chunk, buf)
33✔
827
                        if !yield(chunk) {
33✔
828
                                return
×
829
                        }
×
830

831
                        i := n - 1
33✔
832
                        for i > 0 && indices[i-1] >= indices[i] {
55✔
833
                                i--
22✔
834
                        }
22✔
835
                        if i <= 0 {
37✔
836
                                return
4✔
837
                        }
4✔
838

839
                        j := n - 1
29✔
840
                        for indices[j] <= indices[i-1] {
37✔
841
                                j--
8✔
842
                        }
8✔
843

844
                        indices[i-1], indices[j] = indices[j], indices[i-1]
29✔
845

29✔
846
                        for x, y := i, n-1; x < y; x, y = x+1, y-1 {
42✔
847
                                indices[x], indices[y] = indices[y], indices[x]
13✔
848
                        }
13✔
849
                }
850
        }
851
}
852

853
// Range iterates through elements until the given function returns false.
854
//
855
// The function iterates through the elements of the iterator and applies the provided function
856
// to each element. It stops iteration when the function returns false for an element.
857
//
858
// Params:
859
//
860
// - fn (func(V) bool): The function that evaluates elements for continuation of iteration.
861
//
862
// Example usage:
863
//
864
//        iter := g.Slice[int]{1, 2, 3, 4, 5}.Iter()
865
//        iter.Range(func(val int) bool {
866
//            fmt.Println(val) // Replace this with the function logic you need.
867
//            return val < 5 // Replace this with the condition for continuing iteration.
868
//        })
869
//
870
// The iteration will stop when the provided function returns false for an element.
871
func (seq SeqSlice[V]) Range(fn func(v V) bool) {
3✔
872
        seq(func(v V) bool {
11✔
873
                return fn(v)
8✔
874
        })
8✔
875
}
876

877
// Skip returns a new iterator skipping the first n elements.
878
//
879
// The function creates a new iterator that skips the first n elements of the current iterator
880
// and returns an iterator starting from the (n+1)th element.
881
//
882
// Params:
883
//
884
// - n (uint): The number of elements to skip from the beginning of the iterator.
885
//
886
// Returns:
887
//
888
// - SeqSlice[V]: An iterator that starts after skipping the first n elements.
889
//
890
// Example usage:
891
//
892
//        iter := g.Slice[int]{1, 2, 3, 4, 5, 6}.Iter()
893
//        iter.Skip(3).Collect().Print()
894
//
895
// Output: [4, 5, 6]
896
//
897
// The resulting iterator will start after skipping the specified number of elements.
898
func (seq SeqSlice[V]) Skip(n uint) SeqSlice[V] {
2✔
899
        return func(yield func(V) bool) {
4✔
900
                seq(func(v V) bool {
11✔
901
                        if n > 0 {
15✔
902
                                n--
6✔
903
                                return true
6✔
904
                        }
6✔
905
                        return yield(v)
3✔
906
                })
907
        }
908
}
909

910
// StepBy creates a new iterator that iterates over every N-th element of the original iterator.
911
// This function is useful when you want to skip a specific number of elements between each iteration.
912
//
913
// Parameters:
914
// - n uint: The step size, indicating how many elements to skip between each iteration.
915
//
916
// Returns:
917
// - SeqSlice[V]: A new iterator that produces elements from the original iterator with a step size of N.
918
//
919
// Example usage:
920
//
921
//        slice := g.Slice[int]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
922
//        iter := slice.Iter().StepBy(3)
923
//        result := iter.Collect()
924
//        result.Print()
925
//
926
// Output: [1 4 7 10]
927
//
928
// The resulting iterator will produce elements from the original iterator with a step size of N.
929
func (seq SeqSlice[V]) StepBy(n uint) SeqSlice[V] {
4✔
930
        return func(yield func(V) bool) {
8✔
931
                i := uint(0)
4✔
932
                seq(func(v V) bool {
34✔
933
                        i++
30✔
934
                        if (i-1)%n == 0 {
45✔
935
                                return yield(v)
15✔
936
                        }
15✔
937
                        return true
15✔
938
                })
939
        }
940
}
941

942
// SortBy applies a custom sorting function to the elements in the iterator
943
// and returns a new iterator containing the sorted elements.
944
//
945
// The sorting function 'fn' should take two arguments, 'a' and 'b' of type V,
946
// and return true if 'a' should be ordered before 'b', and false otherwise.
947
//
948
// Example:
949
//
950
//        g.SliceOf("a", "c", "b").
951
//                Iter().
952
//                SortBy(func(a, b string) cmp.Ordering { return b.Cmp(a) }).
953
//                Collect().
954
//                Print()
955
//
956
// Output: Slice[c, b, a]
957
//
958
// The returned iterator is of type SeqSlice[V], which implements the iterator
959
// interface for further iteration over the sorted elements.
960
func (seq SeqSlice[V]) SortBy(fn func(a, b V) cmp.Ordering) SeqSlice[V] {
3✔
961
        items := seq.Collect()
3✔
962
        items.SortBy(fn)
3✔
963

3✔
964
        return items.Iter()
3✔
965
}
3✔
966

967
// Take returns a new iterator with the first n elements.
968
// The function creates a new iterator containing the first n elements from the original iterator.
969
func (seq SeqSlice[V]) Take(n uint) SeqSlice[V] {
1✔
970
        return func(yield func(V) bool) {
2✔
971
                seq(func(v V) bool {
11✔
972
                        if n == 0 {
11✔
973
                                return false
1✔
974
                        }
1✔
975
                        n--
9✔
976
                        return yield(v)
9✔
977
                })
978
        }
979
}
980

981
// ToChan converts the iterator into a channel, optionally with context(s).
982
//
983
// The function converts the elements of the iterator into a channel for streaming purposes.
984
// Optionally, it accepts context(s) to handle cancellation or timeout scenarios.
985
//
986
// Params:
987
//
988
// - ctxs (context.Context): Optional context(s) to control the channel behavior (e.g., cancellation).
989
//
990
// Returns:
991
//
992
// - chan V: A channel containing the elements from the iterator.
993
//
994
// Example usage:
995
//
996
//        iter := g.Slice[int]{1, 2, 3}.Iter()
997
//        ctx, cancel := context.WithCancel(context.Background())
998
//        defer cancel() // Ensure cancellation to avoid goroutine leaks.
999
//        ch := iter.ToChan(ctx)
1000
//        for val := range ch {
1001
//            fmt.Println(val)
1002
//        }
1003
//
1004
// The resulting channel allows streaming elements from the iterator with optional context handling.
1005
func (seq SeqSlice[V]) ToChan(ctxs ...context.Context) chan V {
2✔
1006
        ch := make(chan V)
2✔
1007

2✔
1008
        ctx := context.Background()
2✔
1009
        if len(ctxs) != 0 {
3✔
1010
                ctx = ctxs[0]
1✔
1011
        }
1✔
1012

1013
        go func() {
4✔
1014
                defer close(ch)
2✔
1015

2✔
1016
                for v := range seq {
6✔
1017
                        select {
4✔
1018
                        case <-ctx.Done():
1✔
1019
                                return
1✔
1020
                        default:
3✔
1021
                                ch <- v
3✔
1022
                        }
1023
                }
1024
        }()
1025

1026
        return ch
2✔
1027
}
1028

1029
// Unique returns an iterator with only unique elements.
1030
//
1031
// The function returns an iterator containing only the unique elements from the original iterator.
1032
//
1033
// Returns:
1034
//
1035
// - SeqSlice[V]: An iterator containing unique elements from the original iterator.
1036
//
1037
// Example usage:
1038
//
1039
//        slice := g.Slice[int]{1, 2, 3, 2, 4, 5, 3}
1040
//        unique := slice.Iter().Unique().Collect()
1041
//        unique.Print()
1042
//
1043
// Output: [1, 2, 3, 4, 5].
1044
//
1045
// The resulting iterator will contain only unique elements from the original iterator.
1046
func (seq SeqSlice[V]) Unique() SeqSlice[V] {
1✔
1047
        return func(yield func(V) bool) {
2✔
1048
                seen := NewSet[any]()
1✔
1049
                seq(func(v V) bool {
8✔
1050
                        if !seen.Contains(v) {
12✔
1051
                                seen.Insert(v)
5✔
1052
                                return yield(v)
5✔
1053
                        }
5✔
1054
                        return true
2✔
1055
                })
1056
        }
1057
}
1058

1059
// Zip combines elements from the current sequence and another sequence into pairs,
1060
// creating an ordered map with identical keys and values of type V.
1061
func (seq SeqSlice[V]) Zip(two SeqSlice[V]) SeqMapOrd[V, V] { return zip(seq, two) }
2✔
1062

1063
func zip[V, U any](one SeqSlice[V], two SeqSlice[U]) SeqMapOrd[V, U] {
2✔
1064
        return func(yield func(V, U) bool) {
4✔
1065
                oneNext, oneStop := one.Pull()
2✔
1066
                defer oneStop()
2✔
1067

2✔
1068
                twoNext, twoStop := two.Pull()
2✔
1069
                defer twoStop()
2✔
1070

2✔
1071
                for {
10✔
1072
                        one, ok := oneNext()
8✔
1073
                        if !ok {
9✔
1074
                                return
1✔
1075
                        }
1✔
1076

1077
                        two, ok := twoNext()
7✔
1078
                        if !ok {
8✔
1079
                                return
1✔
1080
                        }
1✔
1081

1082
                        if !yield(one, two) {
6✔
1083
                                return
×
1084
                        }
×
1085
                }
1086
        }
1087
}
1088

1089
// Find searches for an element in the iterator that satisfies the provided function.
1090
//
1091
// The function iterates through the elements of the iterator and returns the first element
1092
// for which the provided function returns true.
1093
//
1094
// Params:
1095
//
1096
// - fn (func(V) bool): The function used to test elements for a condition.
1097
//
1098
// Returns:
1099
//
1100
// - Option[V]: An Option containing the first element that satisfies the condition; None if not found.
1101
//
1102
// Example usage:
1103
//
1104
//        iter := g.Slice[int]{1, 2, 3, 4, 5}.Iter()
1105
//
1106
//        found := iter.Find(
1107
//                func(i int) bool {
1108
//                        return i == 2
1109
//                })
1110
//
1111
//        if found.IsSome() {
1112
//                fmt.Println("Found:", found.Some())
1113
//        } else {
1114
//                fmt.Println("Not found.")
1115
//        }
1116
//
1117
// The resulting Option may contain the first element that satisfies the condition, or None if not found.
1118
func (seq SeqSlice[V]) Find(fn func(v V) bool) (r Option[V]) {
2✔
1119
        seq(func(v V) bool {
9✔
1120
                if !fn(v) {
13✔
1121
                        return true
6✔
1122
                }
6✔
1123
                r = Some(v)
1✔
1124
                return false
1✔
1125
        })
1126

1127
        return r
2✔
1128
}
1129

1130
// Windows returns an iterator that yields sliding windows of elements of the specified size.
1131
//
1132
// The function creates a new iterator that yields windows of elements from the original iterator,
1133
// where each window is a slice containing elements of the specified size and moves one element at a time.
1134
//
1135
// Params:
1136
//
1137
// - n (int): The size of each window.
1138
//
1139
// Returns:
1140
//
1141
// - SeqSlices[V]: An iterator yielding sliding windows of elements of the specified size.
1142
//
1143
// Example usage:
1144
//
1145
//        slice := g.Slice[int]{1, 2, 3, 4, 5, 6}
1146
//        windows := slice.Iter().Windows(3).Collect()
1147
//
1148
// Output: [Slice[1, 2, 3] Slice[2, 3, 4] Slice[3, 4, 5] Slice[4, 5, 6]]
1149
//
1150
// The resulting iterator will yield sliding windows of elements, each containing the specified number of elements.
1151
func (seq SeqSlice[V]) Windows(n Int) SeqSlices[V] {
1✔
1152
        return func(yield func([]V) bool) {
2✔
1153
                if n <= 0 {
1✔
1154
                        return
×
1155
                }
×
1156

1157
                buf := make([]V, n)
1✔
1158
                size := 0
1✔
1159

1✔
1160
                seq(func(v V) bool {
7✔
1161
                        if size < int(n) {
9✔
1162
                                buf[size] = v
3✔
1163
                                size++
3✔
1164
                                if size == int(n) {
4✔
1165
                                        chunk := make([]V, n)
1✔
1166
                                        copy(chunk, buf)
1✔
1167
                                        return yield(chunk)
1✔
1168
                                }
1✔
1169
                                return true
2✔
1170
                        }
1171

1172
                        copy(buf, buf[1:])
3✔
1173
                        buf[n-1] = v
3✔
1174

3✔
1175
                        chunk := make([]V, n)
3✔
1176
                        copy(chunk, buf)
3✔
1177

3✔
1178
                        return yield(chunk)
3✔
1179
                })
1180
        }
1181
}
1182

1183
// FromChan converts a channel into an iterator.
1184
//
1185
// This function takes a channel as input and converts its elements into an iterator,
1186
// allowing seamless integration of channels into iterator-based processing pipelines.
1187
// It continuously reads from the channel until it's closed,
1188
// yielding each element to the provided yield function.
1189
//
1190
// Parameters:
1191
// - ch (<-chan V): The input channel to convert into an iterator.
1192
//
1193
// Returns:
1194
// - SeqSlice[V]: An iterator that yields elements from the channel.
1195
//
1196
// Example usage:
1197
//
1198
//        ch := make(chan int)
1199
//        go func() {
1200
//                defer close(ch)
1201
//                for i := 1; i <= 5; i++ {
1202
//                        ch <- i
1203
//                }
1204
//        }()
1205
//
1206
//        // Convert the channel into an iterator and apply filtering and mapping operations.
1207
//        g.FromChan(ch).
1208
//                Filter(func(i int) bool { return i%2 == 0 }). // Filter even numbers.
1209
//                Map(func(i int) int { return i * 2 }).        // Double each element.
1210
//                Collect().                                    // Collect the results into a slice.
1211
//                Print()                                       // Print the collected results.
1212
//
1213
// Output: Slice[4, 8]
1214
//
1215
// The resulting iterator will yield elements from the provided channel, filtering out odd numbers,
1216
// doubling each even number, and finally collecting the results into a slice.
1217
func FromChan[V any](ch <-chan V) SeqSlice[V] {
1✔
1218
        return func(yield func(V) bool) {
2✔
1219
                for v := range ch {
4✔
1220
                        if !yield(v) {
4✔
1221
                                return
1✔
1222
                        }
1✔
1223
                }
1224
        }
1225
}
1226

1227
func seqSlice[V any](slice []V) SeqSlice[V] {
249✔
1228
        return func(yield func(V) bool) {
502✔
1229
                for _, v := range slice {
974✔
1230
                        if !yield(v) {
750✔
1231
                                return
29✔
1232
                        }
29✔
1233
                }
1234
        }
1235
}
1236

1237
func revSeqSlice[V any](slice []V) SeqSlice[V] {
3✔
1238
        return func(yield func(V) bool) {
6✔
1239
                for i := len(slice) - 1; i >= 0; i-- {
9✔
1240
                        if !yield(slice[i]) {
6✔
1241
                                return
×
1242
                        }
×
1243
                }
1244
        }
1245
}
1246

1247
// works slower
1248
// func dedupSlice[V any](seq SeqSlice[V]) SeqSlice[V] {
1249
//         var current V
1250
//
1251
//         eq := f.Eqd[any]
1252
//         if f.Comparable(current) {
1253
//                 eq = f.Eq
1254
//         }
1255
//
1256
//         return func(yield func(V) bool) {
1257
//                 seq(func(v V) bool {
1258
//                         if eq(current)(v) {
1259
//                                 return true
1260
//                         }
1261
//
1262
//                         current = v
1263
//                         return yield(v)
1264
//                 })
1265
//         }
1266
// }
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc