Replace make([]T, 0, count) + append with make([]T, count) + result[i] = ...
since the final size is known upfront. Eliminates per-element append overhead.
Also adds comprehensive benchmark coverage for all helpers across
core, it, mutable, and parallel packages (282 benchmark functions).
UniqMap previously built a map then called Keys(seen) which:
1. Iterated the map a second time to extract keys
2. Returned keys in non-deterministic map iteration order
3. Allocated a separate slice inside Keys()
Now collects results directly during the single pass, preserving
insertion order and eliminating the redundant iteration.
* perf(Reject): preallocate result slice capacity
Reject was using `Slice{}` (zero capacity) causing multiple
grow-and-copy allocations as elements were appended. Preallocate
with `make(Slice, 0, len(collection))` to eliminate regrowth.
benchstat (strings_1000): -42.96% time, -53.37% memory, -88.89% allocs
* perf(Reject): preallocate result slice in Reject, RejectErr, RejectMap
All three Reject variants were using zero-capacity slices (`Slice{}`
or `[]R{}`), causing multiple grow-and-copy allocations as elements
were appended. Preallocate with `make(..., 0, len(collection))` to
eliminate slice regrowth.
Reject benchstat (strings_1000): -42.96% time, -53.37% memory, -88.89% allocs
RejectErr benchstat (strings_1000): -45.11% time, -53.37% memory, -88.89% allocs
RejectMap benchstat (strings_1000): -47.63% time, -53.37% memory, -88.89% allocs
Fixed DropByIndex function for the case when a negative index exceeds
the slice size. This caused subsequent indices to have incorrect
offsets, leading to incorrect results.
Example of the bug:
DropByIndex([]int{0, 1, 2, 3, 4}, -100, 4)
returned []int{0, 1, 2, 4} instead of []int{0, 1, 2, 3}
Improvements:
- Removed map-based uniqueness check, now uses sorted iteration with O(1) memory
- Added copy of indexes to prevent mutation of input
- Fixed negative index handling logic
- Improved range check using uint for proper bounds validation
Performance:
- Time: -75.61% (geomean)
- Memory: -62.65% (geomean)
- Allocations: -43.67% (geomean)
Additional:
- Optimized Filter and FilterI in mutable/slice.go
- Fix docstring: clarify Slice returns a slice view, not a copy
- Reorder boundary checks to use else-if
- Add test case for negative start and end indices
- CutPrefix now uses HasPrefix instead of manual comparison loop
- CutSuffix now uses HasSuffix instead of manual comparison loop
- TrimPrefix simplified with HasPrefix condition in for loop
- TrimSuffix simplified with HasSuffix condition in for loop
This reduces code duplication and improves readability.
* feat: add Take, TakeWhile, FilterTake, Window, and Sliding functions
Add five new slice manipulation functions with tests, examples, and documentation.
* improve Take function safety and add benchmarks
* rename FilterTake to TakeFilter and add README docs
* remove Window and Sliding benchmarks
* apply gofmt and fix linter errors
* apply gofmt and fix linter errors
* 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>
* 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.
* fix: rename IsSortedByKey to IsSortedBy
---------
Co-authored-by: Franky W. <frankywahl@users.noreply.github.com>
Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
* Add a Concat slice function.
This is a variadic wrapper around Flatten that allows callers
to assemble one slice from many slices without first joining
them into a slice-of-slices.
* Update slice_test.go
---------
Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
* 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>
* lint: pin golangci-lint version
* feat: preserve type alias in WithoutBy
* feat: preserve type alias in DropByIndex
---------
Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
* lint: pin golangci-lint version
* fix: more consistent panic strings
* Update golangci-lint version in workflow
Updated golangci-lint action version to v2.4.
---------
Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
- Modify the iteration function parameters in the UniqueBy, GroupByMap, and Keyify functions to use index access for collection elements.
- Optimize parameter naming in the GroupByMap function to improve code readability.
- Add test cases for the GroupByMap function to cover different types of inputs.
Co-authored-by: ShuQingZai <overbeck.jack@outlook.com>