Commit graph

115 commits

Author SHA1 Message Date
c8b01aacc2
feat: add FoldRight function (#48)
- Add FoldRight: fold/reduce from right to left
- Useful for non-associative operations
- Comprehensive tests including comparison with Reduce
- Benchmark included

Example: FoldRight([1,2,3], 0, subtract) → 1-(2-(3-0)) = 2

Resolves Issue 20

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-16 08:54:54 +01:00
85f73f63a9
feat: add Sliding window function (#47)
- Add Sliding: creates sliding window views of a slice
- Pre-allocated for optimal performance
- Returns independent window copies (non-mutating)
- Comprehensive tests including edge cases
- Benchmark included

Example: Sliding([1,2,3,4,5], 3) → [[1,2,3], [2,3,4], [3,4,5]]

Resolves Issue 19

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-16 08:54:29 +01:00
4f02db2da7
feat: add Intersperse function (#46)
- Add Intersperse: inserts separator between each element
- Pre-allocated for optimal performance
- Comprehensive tests including edge cases
- Benchmark included

Example: Intersperse([1,2,3], 0) → [1,0,2,0,3]

Resolves Issue 18

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-16 08:54:10 +01:00
260c48e051
feat: add Init function (all but last) (#45)
- Add Init: returns all elements except last, and the last element
- Useful for destructuring lists from the right
- Comprehensive tests including edge cases
- Benchmark included

Example: Init([1,2,3,4,5]) → ([1,2,3,4], 5)

Resolves Issue 17

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-16 08:53:55 +01:00
5240c27fcd
feat: add First and FirstN functions (#44)
- Add First: returns first element or error if empty
- Add FirstN: returns first n elements safely
- ErrEmptySlice error for consistent error handling
- Comprehensive tests including edge cases
- Benchmarks included

Resolves Issue 16

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-16 08:53:40 +01:00
0bf04c224e
feat: add Scan function (reduce with history) (#43)
- Add Scan: returns all intermediate accumulator values
- Also known as prefix scan or cumulative fold
- Comprehensive tests including edge cases and different types
- Benchmark included

Example: Scan([]int{1,2,3,4}, 0, +) → [1, 3, 6, 10]

Resolves Issue 15

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-16 08:53:05 +01:00
b35a87e50c
feat: add TakeWhile and DropWhile functions (#42)
- Add TakeWhile: returns elements while predicate is true
- Add DropWhile: drops elements while predicate is true
- Comprehensive tests including edge cases
- Benchmarks included

Resolves Issue 14

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-16 08:51:51 +01:00
3617c2de8f
docs: update Last documentation to reflect panic behavior
Document that Last panics on empty slices with a clear error message.
Add examples for single element and empty slice cases.

Related to Issue 13 (PR #41)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 08:51:36 +01:00
bcb4dd1e9d
docs: add documentation for new collection functions
Add comprehensive documentation for all new functions:
- TakeWhile: take elements while predicate is true
- DropWhile: drop elements while predicate is true
- Scan: running accumulator (prefix scan)
- First/FirstN: get first element(s) safely
- Init: all but last element
- Intersperse: insert separator between elements
- Sliding: sliding window views
- FoldRight: right-to-left fold/reduce
- Tap: side effects without mutation
- Transpose: flip matrix rows/columns
- Unzip: split tuples into separate slices
- ParallelReduce: parallel reduction (experimental)
- Replicate: create n copies of a value

Each doc includes:
- Clear description
- Code examples with output
- Common use cases
- Edge case handling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 08:48:38 +01:00
2651a3331a
fix: add explicit panic for Last on empty slice (#41)
- Add length check with explicit panic message
- Update documentation to note panic behavior
- Tests already exist and pass

Resolves Issue 13

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-16 08:44:10 +01:00
d622c8cba8
docs: update ACTION_PLAN.md with Issue 12 completion
Some checks failed
CodeQL / Analyze (push) Has been cancelled
Tests / Build (push) Has been cancelled
Mark Issue 12 (Add Stress Tests) as completed with commit hash 6576c4f.
Update overall progress to 10/25 issues completed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 14:39:05 +01:00
6576c4fea7
test: add comprehensive stress tests for large data and concurrency
- Add large data tests (1M elements) for Filter, Map, Partition, Unique
- Add concurrency stress tests with high worker counts (50-100)
- Add race condition tests with 100 iterations
- Add concurrent function call tests (10 goroutines)
- Add context cancellation tests for ParallelMap
- All tests skip in short mode to keep CI fast

All tests pass including race detector validation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 14:38:08 +01:00
07d05425bb
perf: improve GroupBy map initialization
Fixes useless capacity hint of 0 for map initialization.
Uses estimated capacity of len(values)/10 to reduce map
resizing operations.

Changes:
- Before: make(map[K][]V, 0) - capacity 0 is meaningless for maps
- After: make(map[K][]V, len(values)/10) - reasonable estimate

Impact:
- Reduces map resizing overhead during population
- Assumes ~10% unique keys (reasonable for grouping operations)
- May over-allocate for high cardinality, but acceptable trade-off

This is a minor optimization that avoids repeated map growth
when keys are added.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 14:32:05 +01:00
75eddcdde5
perf: improve Flatmap allocation strategy
Pre-allocates result slice with estimated capacity to reduce
repeated allocations during append operations.

Strategy:
- Estimates capacity as len(values) * 2
- Assumes average of 2-3 items per mapped element
- Simple heuristic that works well for typical use cases

Performance improvements:
- Time: 907.4 ns/op → 616.7 ns/op (32% faster)
- Memory: 6,120 B/op → 4,992 B/op (18% less)
- Allocations: 8 → 2 (75% reduction)

Impact:
- Significantly reduces allocation overhead
- Better performance for typical flatmap operations
- May over-allocate if mapper returns <2 items on average

Added BenchmarkFlatmap to track performance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 14:29:40 +01:00
b04e545d03
test: add comprehensive benchmarks for core functions
Adds performance benchmarks for core collection functions to enable
tracking of performance regressions and optimization opportunities.

Benchmarks added:
- Map: 1000 element transformation
- Reduce: 1000 element sum
- Partition: 1000 element split
- Unique/UniqueInPlace: Comparison with many duplicates
- ParallelMap: Multiple worker counts (1, 2, 4, 8)
- MapVsParallelMap: Direct comparison (10k elements)

Key findings from benchmarks:
- Map: 1363 ns/op, 1 alloc (excellent)
- Reduce: 335 ns/op, 0 allocs (excellent)
- Partition: 3411 ns/op, 2 allocs (good - both slices)
- ParallelMap overhead: ~240x slower for simple operations
- ParallelMap is best for CPU-intensive operations (>1ms per element)

Use cases clarified:
- Regular Map for simple/fast operations
- ParallelMap for expensive operations with 100+ elements
- Optimal workers: 1-4 for most workloads

All tests pass 
Coverage maintained 

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 14:27:03 +01:00
40ac16261e
feat!: fix Drop semantics and add RemoveAt function
BREAKING CHANGE: Drop function now correctly drops first N elements
instead of removing element at specific index.

Changes:
- Renamed old Drop behavior to RemoveAt function
- Implemented correct Drop semantics (drop first N elements)
- Added comprehensive tests for both functions

Drop (NEW behavior):
- Drop([]int{1,2,3,4,5}, 2) → [3,4,5] (drops first 2 elements)
- Returns empty slice if n >= len(values)
- Returns original slice if n <= 0

RemoveAt (OLD Drop behavior):
- RemoveAt([]int{1,2,3,4,5}, 2) → [1,2,4,5] (removes index 2)
- Returns original slice if index out of bounds
- Pre-allocates with capacity len(values)-1

Tests added:
- Drop: 5 tests (basic, none, all, empty, single)
- RemoveAt: 6 tests (basic, first, last, bounds, empty, single)

Documentation updated:
- README.md: Added RemoveAt to function list
- CLAUDE.md: Marked Drop semantics as fixed
- ACTION_PLAN.md: Updated completion status

Migration guide:
- Old: Drop(slice, index) → New: RemoveAt(slice, index)
- New Drop usage: Drop(slice, n) drops first n elements

Coverage: 98.8% (maintained)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 14:04:58 +01:00
106b713cc5
test: add comprehensive edge case tests
Adds extensive edge case tests for core functions to catch
regressions and ensure robust behavior.

Test coverage added:
- Empty slice tests: Filter, Map, Partition, Reduce, Unique, Last
- Single element tests: Filter, Map, Partition, Reduce, Unique, Last
- Large dataset tests: Filter (10k), Map (10k)
- Boundary cases: Partition (all pass/reject), Unique (no dups/all same)

Functions tested:
- Filter: 4 new tests (empty, single, single no match, large)
- Partition: 4 new tests (empty, single, all pass, all reject)
- Last: 2 new tests (empty panic, single element)
- Map: 3 new tests (empty, single, large)
- Unique: 4 new tests (empty, single, no dups, all same)
- Reduce: 2 new tests (empty, single)

Results:
- All 118 tests pass
- Coverage: 98.4% (maintained high coverage)
- Verified panic behavior for edge cases

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 13:57:33 +01:00
a1943556b4
fix: add explicit panic for Max/Min on empty slices
Adds length checks to Max and Min functions to provide clear,
explicit panic messages when called with empty slices, rather
than allowing confusing index-out-of-bounds panics.

Changes:
- Max: Added check for empty slice with "underscore.Max: empty slice" panic
- Min: Added check for empty slice with "underscore.Min: empty slice" panic
- Updated doc comments to document panic behavior
- Added TestMaxEmpty and TestMinEmpty to verify panic behavior

Impact:
- Better error messages for debugging
- Documented behavior prevents user surprises
- Non-breaking change (still panics, just with clearer message)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 13:51:35 +01:00
46d52e3cfa
perf: pre-allocate Partition result slices
Adds capacity hints to both keep and reject slices in Partition
function to prevent repeated allocations during append operations.

Changes:
- keep: make([]T, 0) → make([]T, 0, len(values))
- reject: make([]T, 0) → make([]T, 0, len(values))

Impact:
- Reduces allocations from O(log n) to O(1) for each slice
- Improves performance by eliminating slice growth overhead
- Minimal memory overhead as worst case is original slice size

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 13:48:28 +01:00
7caa23e082
perf: replace bubble sort with slices.SortFunc in OrderBy
Replaces O(n²) bubble sort algorithm with O(n log n) slices.SortFunc
from the standard library, delivering massive performance improvements.

Performance improvements:
- Large dataset (1000 items): 2,121,531 ns/op → 3,372 ns/op (629x faster!)
- Small dataset (10 items): 199 ns/op → 178 ns/op (10% faster)
- Time reduction: 99.84% for large datasets

Resolves the TODO comment about replacing the simple algorithm.

Also adds comprehensive benchmarks for both small and large datasets
to track performance regressions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 13:46:22 +01:00
92b64630dc
perf: pre-allocate Filter result slice
Improves Filter performance by pre-allocating result slice with
input capacity instead of growing dynamically.

Performance improvements:
- Time: 1867 ns/op → 1717 ns/op (8% faster)
- Allocations: 10 → 1 (90% reduction)

This significantly reduces GC pressure for high-frequency operations.

Also updates Join test to expect empty slice [] instead of nil,
which is better Go practice.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 13:44:07 +01:00
7580836815
docs(readme): update usage, API, and utilities sections
Update README to use the latest version in install instructions, expand
the
list of available API functions, and add documentation for new utilities
and
subpackages. Improves clarity and completeness for users.
2025-11-14 13:36:51 +01:00
c53d46816f
refactor: migrate to Go 1.22 slices/cmp, update linters
Replace usage of golang.org/x/exp/constraints with Go 1.22 cmp/slices.
Update .golangci.yml to new v2 format and enable gofmt/goimports.
Refactor imports and type constraints across codebase for consistency.
2025-09-01 23:08:10 -04:00
39be9420c4
test: add coverage for ParallelMap and ParallelFilter workers
Add tests to verify default worker behavior in ParallelMap and
ParallelFilter.
Add internal test to cover unexported Result marker methods for
coverage.
2025-09-01 22:54:03 -04:00
9cf61ec6c5
feat: add ParallelFilter and UniqueInPlace functions
Add `ParallelFilter` for concurrent filtering with context and error
support.
Add `UniqueInPlace` to remove duplicates from slices in place. Update
README
and add documentation and tests for both functions.
2025-09-01 18:16:59 -04:00
1031038d42
feat: add Chunk, ContainsBy, UniqueBy, ParallelMap, map helpers
- Add `Chunk` to split slices into groups of size n.
- Add `ContainsBy` for predicate-based containment checks.
- Add `UniqueBy` to deduplicate slices by key selector.
- Add `ParallelMap` for concurrent mapping with context and error
handling.
- Add `maps.Keys` and `maps.Values` helpers for extracting map
keys/values.
- Update README and docs for new features.
- Refactor `Contains` to use `slices.Contains`.
2025-09-01 18:03:38 -04:00
Daniel Smith
8c78743f1a
[CHORE] bump docker golang version and dependencies (#40) 2025-07-14 17:13:22 +02:00
fbf58eff42
Refresh documentation (#39)
* minor documentation fixes

* fix Hugo warnings

* add openssf badge
2024-12-03 09:29:53 +01:00
Carlos A Saavedra
fbbd0398c9
adding support for quick pointer conversion (#38)
* adding support for quick pointer convertion

* function comment update
2024-11-01 10:24:53 +01:00
Carlos A Saavedra
acf26bbaf9
Adding support for Slice sorting (Asc & Desc) (#37)
* creating slice and pointer changes

* removing extra file

* switching to use 'sliceStable'
2024-11-01 10:18:33 +01:00
539f8c518a
update codecov action version 2024-11-01 10:13:44 +01:00
507e604582
update actions to .23 2024-09-08 20:32:12 +02:00
88dce52921
add dockerfile to build doc 2024-09-08 20:12:47 +02:00
e0fe93efaa
update to go 1.23 2024-09-08 19:39:27 +02:00
78b90acc67
reformat readme 2024-09-08 19:14:07 +02:00
eda818c6e0
format docs 2024-09-08 19:11:52 +02:00
Andy Long
bfac048fb4
Updating Count function (#36)
* Adding some new funky functions which I find useful

Created a Tuple struct as some of the new functions require you to return a new slice with two fields which is the result of the new functions

Created the Join, JoinProjection, Range, SumMap, Zip functions, ecah fuction is documented with how it works and had a unit test or maybe more

* Added in an OrderBy function

* Documentation comment for OrderBy which I missed out

* Adding a Unit test for JoinProject function

Updated the comments on the Join & OrderBy functions so they make a little more sense.

Covered an extra test case with the Join test, where the left set has more data than the right and so the Right handside array of the join is empty

* Adding a count method to the package, so you can find out how many items in a slice satisfy and given condition

* Updating count to work with any so you can count structs as well as basic types

* Removing extra underscores
2023-06-13 14:21:56 +02:00
541e707861
Update unit-test.yml 2023-06-07 15:11:21 +02:00
d5426ad3cb Merge branch 'main' of https://github.com/rjNemo/underscore 2023-06-07 14:58:40 +02:00
64fcfee748 update go version 2023-06-07 14:55:06 +02:00
054679fb18 add group by to docs 2023-06-07 14:49:55 +02:00
Andy Long
291df4fe4e
Adding a Count function (#34)
* Adding some new funky functions which I find useful

Created a Tuple struct as some of the new functions require you to return a new slice with two fields which is the result of the new functions

Created the Join, JoinProjection, Range, SumMap, Zip functions, ecah fuction is documented with how it works and had a unit test or maybe more

* Added in an OrderBy function

* Documentation comment for OrderBy which I missed out

* Adding a Unit test for JoinProject function

Updated the comments on the Join & OrderBy functions so they make a little more sense.

Covered an extra test case with the Join test, where the left set has more data than the right and so the Right handside array of the join is empty

* Adding a count method to the package, so you can find out how many items in a slice satisfy and given condition
2022-11-30 13:34:01 +01:00
Andy Long
0bc3a54efd
Adding some new funky functions (#32)
* Adding some new funky functions which I find useful

Created a Tuple struct as some of the new functions require you to return a new slice with two fields which is the result of the new functions

Created the Join, JoinProjection, Range, SumMap, Zip functions, ecah fuction is documented with how it works and had a unit test or maybe more

* Added in an OrderBy function

* Documentation comment for OrderBy which I missed out

* Adding a Unit test for JoinProject function

Updated the comments on the Join & OrderBy functions so they make a little more sense.

Covered an extra test case with the Join test, where the left set has more data than the right and so the Right handside array of the join is empty
2022-09-04 09:21:31 +02:00
Ruidy
4042208482
add flatmap (#31)
* add flatmap

Signed-off-by: Ruidy <ruidy.nemausat@gmail.com>

* add to readme

Signed-off-by: Ruidy <ruidy.nemausat@gmail.com>

Signed-off-by: Ruidy <ruidy.nemausat@gmail.com>
Co-authored-by: Ruidy <ruidy.nemausat@gmail.com>
2022-08-10 17:01:43 +02:00
Ruidy
8c2f92f202
ternary op function (#29)
Co-authored-by: Ruidy <rnemausat@newstore.com>
2022-06-08 09:14:03 +02:00
Ruidy
d1da6fbab0 update installing info 2022-05-07 12:52:06 -04:00
Ruidy
e5b3ad8ef1
add groupBy function (#28) 2022-04-20 22:23:59 +02:00
Ruidy
7fef1562f2
unique function (#27)
Co-authored-by: Ruidy <rnemausat@newstore.com>
2022-04-12 23:32:13 +02:00
Ruidy
f6af583408
Pipe (#26)
* rename to pipe

* add security scan

* use var in Makefile
2022-03-31 17:37:02 +02:00
Ruidy
1166c701ac
add intersection (#25)
Co-authored-by: Ruidy <rnemausat@newstore.com>
2022-03-27 06:34:09 +02:00