36 Commits

Author SHA1 Message Date
Samuel Berthe 4d1dbfadf7 chore(linter): adding modernize linter (#841) 2026-03-08 00:17:11 +01:00
Samuel Berthe e9ad51b03a perf: add map capacity hints to Mode and it.UniqKeys/UniqValues (#837)
- Mode: make(map[T]int) → make(map[T]int, len(collection))
- it.UniqKeys: compute total size from input maps for seen map hint
- it.UniqValues: compute total size from input maps for seen map hint

Avoids repeated map rehashing as entries are added.
2026-03-06 17:10:17 +01:00
Samuel Berthe fa095e4b4f fix(doc): fix go playground demo URL (#832)
* fix(doc): fix go playground demo URL

* fix(doc): add more go playground demo URL
2026-03-06 00:09:59 +01:00
Adam Szaraniec 56ef3beaf8 feat: support for buffer iterator (#824)
* support for buffer iterator

* Code review fix

* fix: transforming the Buffer helper into a pull-based operator (it receives an iterator instead of channel)

* doc(it): adding loit.Buffer to doc

---------

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
2026-03-02 16:07:14 +01:00
d-enk c49f84658a perf: lazy it.Reverse iteration instead of in-place mutation (#814)
Replace mutable.Reverse() with lazy iteration from end.
This avoids unnecessary array mutation and reduces overhead.
2026-02-25 20:59:44 +01:00
d-enk b27b00635d perf: avoid unnecessary error allocation in NthOr, NthOrEmpty (#817)
Extract core logic into sliceNth/seqNth func returning (T, bool) instead of (T, error).

NthOr and NthOrEmpty now use these directly,
avoiding fmt.Errorf allocation when nth is out of bounds.
2026-02-25 20:50:51 +01:00
d-enk b0b5cc3adf perf: preallocate result slice in RangeWithSteps (#820)
- RangeWithSteps now preallocates result slice using math.Ceil for better performance
- Fix edge cases for floating point values with small steps
- Add test cases for float and custom type validation
- Rename TestRangeClose → TestRangeWithSteps for consistency
- Simplify ChunkEntries chunk count calculation using ((count-1)/size)+1 formula
2026-02-25 20:48:26 +01:00
d-enk d0901349e7 perf: optimize it.ContainsBy, EveryBy, SomeBy, NoneBy to avoid unnecessary allocations (#812)
Replace intermediate iterator chains with direct loops and early returns.

The direct loops with early return eliminate intermediate iterator
creation from Filter(), Reject(), IsNotEmpty() and IsEmpty() functions.

Benchmark results (benchstat):
                         │    old.txt    │               new.txt               │
                         │    sec/op     │    sec/op     vs base               │
ItContainsBy/ints_10-4      807.2n ± 54%   151.0n ±  6%  -81.29% (p=0.000 n=8)
ItContainsBy/ints_100-4     2.447µ ± 14%   1.531µ ± 11%  -37.42% (p=0.000 n=8)
ItContainsBy/ints_1000-4    17.67µ ±  4%   13.85µ ±  4%  -21.64% (p=0.000 n=8)
ItEveryBy/ints_10-4        1022.5n ± 63%   208.0n ± 34%  -79.66% (p=0.000 n=8)
ItEveryBy/ints_100-4        5.640µ ± 36%   1.542µ ±  9%  -72.67% (p=0.000 n=8)
ItEveryBy/ints_1000-4       52.22µ ± 54%   19.29µ ± 16%  -63.06% (p=0.000 n=8)
ItSomeBy/ints_10-4         2227.5n ± 43%   187.1n ± 14%  -91.60% (p=0.000 n=8)
ItSomeBy/ints_100-4         4.611µ ± 22%   1.691µ ± 10%  -63.32% (p=0.000 n=8)
ItSomeBy/ints_1000-4        39.41µ ± 27%   22.61µ ± 24%  -42.63% (p=0.000 n=8)
ItNoneBy/ints_10-4         1657.5n ± 34%   196.3n ± 21%  -88.15% (p=0.000 n=8)
ItNoneBy/ints_100-4         4.503µ ± 20%   1.743µ ± 12%  -61.30% (p=0.000 n=8)
ItNoneBy/ints_1000-4        29.39µ ± 29%   16.66µ ± 15%  -43.32% (p=0.000 n=8)
geomean                     5.591µ         1.747µ        -68.76%

                         │  old.txt   │               new.txt                │
                         │    B/op    │   B/op    vs base                    │
ItContainsBy/ints_10-4     200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItContainsBy/ints_100-4    200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItContainsBy/ints_1000-4   200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_10-4        184.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_100-4       184.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_1000-4      184.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_10-4         200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_100-4        200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_1000-4       200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_10-4         200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_100-4        200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_1000-4       200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)

                         │  old.txt   │                new.txt                 │
                         │ allocs/op  │ allocs/op   vs base                    │
ItContainsBy/ints_10-4     7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItContainsBy/ints_100-4    7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItContainsBy/ints_1000-4   7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_10-4        6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_100-4       6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_1000-4      6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_10-4         7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_100-4        7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_1000-4       7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_10-4         7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_100-4        7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_1000-4       7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
2026-02-24 20:26:59 +01:00
d-enk b33df06020 perf: optimize it.Find to avoid unnecessary allocations (#811)
Replace First(Filter(collection, predicate)) with direct loop implementation.

The direct loop with early return eliminates intermediate iterator
creation from Filter() and First() functions.

Benchmark results:
                   │   old.txt    │               new.txt               │
                   │    sec/op    │    sec/op     vs base               │
ItFind/ints_10-4     521.3n ± 14%   157.3n ±  8%  -69.82% (p=0.000 n=8)
ItFind/ints_100-4    1.913µ ± 13%   1.545µ ± 22%  -19.26% (p=0.002 n=8)
ItFind/ints_1000-4   17.07µ ±  7%   12.88µ ±  1%  -24.59% (p=0.000 n=8)
geomean              2.573µ         1.462µ        -43.15%

                   │  old.txt   │               new.txt                │
                   │    B/op    │   B/op    vs base                    │
ItFind/ints_10-4     192.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItFind/ints_100-4    192.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItFind/ints_1000-4   192.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)

                   │  old.txt   │                new.txt                 │
                   │ allocs/op  │ allocs/op   vs base                    │
ItFind/ints_10-4     7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItFind/ints_100-4    7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItFind/ints_1000-4   7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
2026-02-24 20:25:28 +01:00
d-enk fc6b369dd2 perf: optimize it.CountBy by removing Filter iterator chain (#813)
- Remove unnecessary Filter(collection, predicate) chain
- Use direct loop with predicate check instead
- Results: -36.68% time geomean, -100% B/op, -100% allocs/op

Benchstat results:
                      │   old.txt    │              new.txt               │
                      │    sec/op    │   sec/op     vs base               │
ItCountBy/ints_10-4     433.0n ± 23%   186.2n ± 5%  -56.99% (p=0.000 n=8)
ItCountBy/ints_100-4    2.487µ ± 27%   1.678µ ± 6%  -32.55% (p=0.000 n=8)
ItCountBy/ints_1000-4   20.16µ ±  8%   17.64µ ± 4%  -12.50% (p=0.005 n=8)
geomean                 2.790µ         1.766µ       -36.68%

                      │  old.txt   │               new.txt                │
                      │    B/op    │   B/op    vs base                    │
ItCountBy/ints_10-4     160.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItCountBy/ints_100-4    160.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItCountBy/ints_1000-4   160.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)

                      │  old.txt   │                new.txt                 │
                      │ allocs/op  │ allocs/op   vs base                    │
ItCountBy/ints_10-4     6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItCountBy/ints_100-4    6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItCountBy/ints_1000-4   6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
2026-02-24 20:23:49 +01:00
d-enk 6b8eea7994 refactor: use separate variables for each iter.Pull in it.Zip functions (#816)
Replace shared next struct and reused stop variable with separate
nextA, stopA, nextB, stopB, etc.

Improves code clarity and eliminates potential confusion from variable reuse.
2026-02-24 20:21:56 +01:00
Yuliya c1d11cb658 Add iterator slice helpers (#791)
* add iterator slice helpers and channel dedup/tee

* note unbounded memory growth in Distinct; simplify Take

* avoid extra iteration in Take/TakeWhile/TakeFilter and precompute Sliding step

* avoid reallocations in Sliding overlap shift

* sliding uses ring buffer

* refactor Sliding and expand TestSliding

* Remove Tee; add TakeFilter variant, rewrite Sliding

* remove channel Distinct/DistinctBy

* TakeFilter/TakeFilterI for slice

* Revert "TakeFilter/TakeFilterI for slice"

This reverts commit 6d2fcdc07b.

* doc  add new helpers to llms.txt

---------

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
2026-02-23 20:27:51 +01:00
Tolochik Igor Vladimirovich 48d6af1394 fix: reset n counter per iteration in it.Replace (#799) 2026-02-21 19:24:13 +01:00
Samuel Berthe 34e2ec595d style: fix linter (#802) 2026-02-16 15:42:42 +01:00
d-enk a822176cba perf: optimize it.Trim to use DropLastWhile(DropWhile(...)) (#780)
Change Trim to use DropLastWhile(DropWhile(...)) instead of DropWhile(DropLastWhile(...))

This is more efficient because DropWhile doesn't use a buffer, so it removes
leading elements first, then DropLastWhile works with a smaller collection.
2026-02-08 02:35:49 +01:00
d-enk 73a8fc6255 refactor: improve SamplesBy performance and revert non-panic behavior for negative count (#786)
Regression introduced in 1c66270 (perf: preallocate result slice in SamplesBy) where
`make(Slice, count)` with negative count causes panic. Previously used
`Slice{}` with `append`, which handled negative counts gracefully.

- Simplify NthOrEmpty by removing redundant error handling
- Simplify Sample by removing intermediate variable
- Refactor SamplesBy to use index tracking instead of collection copying
  - More efficient: avoids copying the entire collection
  - Uses Range to generate indexes and swaps/removes from index slice
  - Uses `n := len(indexes)` to eliminate redundant bounds checks
- Add early return for count <= 0 in SamplesBy (fixes panic with make)
- Add edge case tests for SamplesBy:
  - Test with deterministic random generators (always last index, always 0)
  - Test count = 0 and count = -1 (verifies non-panic behavior)
  - Add panic test for out-of-range index generation
2026-02-08 02:34:53 +01:00
Samuel Berthe fedd0b6d2d doc: explain chunkstring inconsistency (#789)
* doc: explain chunkstring inconsistency

* doc: explain chunkstring inconsistency
2026-01-27 18:53:04 +01:00
d-enk d61098016a refactor(it): simplify DropLast, TrimSuffix/Prefix and use range loops (#782) 2026-01-22 17:51:20 +01:00
d-enk 2859d7382f perf: use Ternary() instead If().Else() in Range/RangeFrom (#770)
No allocs in it.Range, it.RangeFrom

Add more tests
2026-01-13 11:34:46 +01:00
d-enk 775539002b perf: correct prealloc of the result in FindUniques/Duplicates[By] (#764)
Track exact duplicate count during detection phase instead of
incorrect estimating capacity as len(collection)-len(isDupl).

Also simplify map update logic and rename ok -> seen for clarity.
2026-01-12 21:03:33 +01:00
d-enk 7a0a18b3a4 perf: optimize PartitionBy by eliminating redundant append (#765)
New groups are now initialized with the first element directly,
avoiding an extra append operation in the hot loop.

Use a one style for lo/it/parallel
2026-01-12 20:58:04 +01:00
d-enk da548925c1 refactor: simplify it.HasSuffix implementation (#767)
Simplify circular buffer logic:
- simplified calculation of the buf index
- remove append-based construction
- reduce unnecessary copying
2026-01-12 20:52:16 +01:00
d-enk 7d777446ab refactor: simplify for loop (#772)
* refactor: use available in go1.23 range over int in `it.Times`

* refactor: use range over chan in `ChannelDispatcher`
2026-01-12 20:40:20 +01:00
d-enk a2553e57bb refactor: improve lo[it].Intersect[By] readability and performance (#756)
* refactor: improve lo[it].Intersect[By] readability and performance

Preallocate seen map capacity.

Extract first and last list handling out of the main loop.

Remove redundant map traversal by combining the reset and delete
passes into a single loop. Values are now initialized to false and
toggled to true when found, allowing the cleanup pass to both reset
(true→false) and delete in one iteration.

Move len(seen) == 0 check into loop condition, allowing early exit
before processing next list when intersection becomes empty
(skips redundant first iteration).

* fix([it].Intersect[By]): remove incorrect early return for single list

The special case `if len(lists) == 1 { return lists[0] }` was buggy:
- Returned the original slice instead of a new one
- Did not deduplicate elements

Removing it allows the general algorithm to handle single lists
correctly by creating a new slice with unique elements.
2026-01-08 17:54:23 +01:00
d-enk 27e2842ca8 fix(iter/tuples): support break iteration over Zip[By] seq (#757)
fix all https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/yield
2026-01-07 21:31:02 +01:00
Samuel Berthe d99edab80d Refactoring lo.IntersectBy + adding loit.IntersectBy + adding doc (#739)
* feat(intersectby): form transform callback in first position and add support for vaarg

* feat(it): adding loit.IntersectBy

* doc: adding lo.IntersectBy + loit.IntersectBy

* doc: adding lo.IntersectBy + loit.IntersectBy

* style: fix linter

* doc: adding example for lo.IntersectBy
2025-11-07 01:23:34 +01:00
Nathan Baulch e7386d9246 lint: fix inconsistent callback function parameter names (#730)
* Fix linting

* Use is.ElementsMatch

This will ignore the ordering of the final intersection. Especially
important when checking old versions of go that do not guarantee an order
when iterating through maps.

* lint: fix inconsistent callback function parameter names

* lint: rename "iteratee" to "transform" for *Map helpers

* lint: rename "project" parameters to "transform"

* lint: rename "cb" parameters to "callback"

* lint: rename "iteratee" to "callback" for ForEach helpers

---------

Co-authored-by: Franky W. <frankywahl@users.noreply.github.com>
Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
2025-11-06 18:05:11 +01:00
Samuel Berthe 9cdabc1420 feat(perf): speed up some functions with linear complexity O=n2 -> O=2n (#726) 2025-11-05 19:07:43 +01:00
Samuel Berthe 734a6b156c feat(it): adding loit.Concat (#722) 2025-10-25 21:11:08 +02:00
Samuel Berthe 29dcc41a9c style: reduce the number of files in root directory (because you need to scroll too many times before reading the readme) (#719) 2025-10-24 20:14:51 +02:00
Samuel Berthe bc738690ca style: fix linter 2025-10-12 18:24:32 +02:00
Anurag Ojha 02d371c58e fix(it.Mode): align behavior with lo.Mode and ensure consistent slice… (#711)
* fix(it.Mode): align behavior with lo.Mode and ensure consistent slice capacity

* replicating test section in main package
2025-10-12 15:58:37 +02:00
Samuel Berthe 15ac624913 docs: adding go playground examples to it/ package (#708) 2025-10-08 15:54:22 +02:00
Samuel Berthe 18c5a43f79 Style/rename internal rand (#701)
* style: rename internal/rand package to internal/xrand

* doc: internal package readme

* oops
2025-10-05 00:42:41 +02:00
Marat Abrarov 7d7222b803 feat: from slice/iterator to map with index passed (#698)
* feat: implementation of conversion from slice to map without index passed to transformation function through the similar conversion but with index passed to transformation function.

Signed-off-by: Marat Abrarov <abrarov@gmail.com>

* feat: implementation of conversion from iterator to map without index passed to transformation function through the similar conversion but with index passed to transformation function.

Signed-off-by: Marat Abrarov <abrarov@gmail.com>

---------

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
2025-10-03 02:05:55 +02:00
Nathan Baulch 43cef1f439 feat: new iter package (#672)
* lint: pin golangci-lint version

* lint: fix issues triggered by go1.23 upgrade

* feat: new iter package

* lint: fix linter issues

* fix: restore go1.18

* fix: rename package to "it"

* feat: assign multiple sequences of maps

* fix: panic in DropRight if n = 0

* docs: fix incorrect non-iter helper references

* feat: implement Invert helper

* feat: helpers for creating and checking empty sequences

* feat: implement Reverse helper

* feat: implement ReduceRight helper

* feat: implement Shuffle helper

* feat: implement Sample* helpers

* refactor: rename helpers with Seq convention

* feat: implement SeqToChannel2 helper

* feat: implement HasPrefix/HasSuffix helpers

* chore: port recent changes

* perf: only iterate collection once in Every

* refactor: reduce dupe code by reusing helpers internally

* perf: reuse internal Mode slice

* feat: implement Length helper

* chore: duplicate unit tests for *I helpers

* fix: omit duplicates in second Intersect list

* feat: intersect more than 2 sequences

* feat: implement Drain helper

* feat: implement Seq/Seq2 conversion helpers

* refactor: rename *Right* to *Last*

* chore: minor cleanup

* refactor: consistent predicate/transform parameter names

* perf: abort Slice/Subset once upper bound reached

* refactor: rename IsSortedByKey to IsSortedBy

* refactor: reuse more helpers internally

* feat: implement Cut* helpers

* feat: implement Trim* helpers

* perf: reduce allocations

* docs: describe iteration and allocation expectations

* Update .github/workflows/lint.yml

---------

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
2025-10-02 19:23:16 +02:00