Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ go install honnef.co/go/tools/cmd/staticcheck@latest && staticcheck ./...

**Testing**: All tests are `Example` functions — they serve as both documentation and regression tests. No traditional unit tests. Run a single example with `go test -run ExampleFunctionName`.

**Commit tags**: Commit messages use `#patch`, `#minor`, `#major`, or `#none` suffixes for automated semantic version bumping.
**Commit tags**: Commit messages use `#patch`, `#minor`, `#major`, or `#none` suffixes for automated semantic version bumping. Changing the Go version in `go.mod` should use `#minor`.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ Golang's "missing" iterator/sequence functions.
* `FindBy(iter.Seq[T], func(T) bool) (T, int, bool)`: Returns the first value for which the function returns true
* `FindByKey(iter.Seq2[K,V], K) (V, int, bool)`: Returns the value of the first key-value pair with the given key
* `FindByValue(iter.Seq2[K,V], V) (K, int, bool)`: Returns the key of the first key-value pair with the given value
* `At(iter.Seq[T], int) (T, bool)`: Returns the value at the given 0-based index, or zero value and false if out of range
* `AtKV(iter.Seq2[K,V], int) (K, V, bool)`: Returns the key and value at the given 0-based index, or zero values and false if out of range

## Utility Functions

Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/freeformz/seq

go 1.25

retract v0.2.3
43 changes: 43 additions & 0 deletions seq.go
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,49 @@ func MapToKV[T, K, V any](seq iter.Seq[T], fn func(T) (K, V)) iter.Seq2[K, V] {
}
}

// At returns the value at the given 0-based index in the sequence and true. If
// the index is out of range (negative or beyond sequence length), it returns
// the zero value and false. The provided sequence is iterated over up to and
// including the target index when At is called.
func At[T any](seq iter.Seq[T], index int) (T, bool) {
if index < 0 {
var z T
return z, false
}
var i int
for v := range seq {
if i == index {
return v, true
}
i++
}
var z T
return z, false
}

// AtKV returns the key and value at the given 0-based index in the sequence and true. If
// the index is out of range (negative or beyond sequence length), it returns
// the zero values and false. The provided sequence is iterated over up to and
// including the target index when AtKV is called. To find a value by key, use
// FindByKey instead.
func AtKV[K any, V any](seq iter.Seq2[K, V], index int) (K, V, bool) {
if index < 0 {
var zk K
var zv V
return zk, zv, false
}
var i int
for k, v := range seq {
if i == index {
return k, v, true
}
i++
}
var zk K
var zv V
return zk, zv, false
}

// Find returns the index of the first occurrence of the value in the sequence, the "index" (0 based) of the value, and true. If
// the value is not found, the first return value is the length of the sequence, the second return value is false. The provided
// sequence is iterated over when Find is called.
Expand Down
74 changes: 74 additions & 0 deletions seq_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,80 @@ func ExampleMapToKV() {
// C 3
}

func ExampleAt() {
i := With(1, 2, 3, 4, 5)

fmt.Println(At(i, 2))

// Output:
// 3 true
}

func ExampleAt_outOfRange() {
i := With(1, 2, 3)

fmt.Println(At(i, 5))

// Output:
// 0 false
}

func ExampleAt_empty() {
i := With[int]()

fmt.Println(At(i, 0))

// Output:
// 0 false
}

func ExampleAt_negative() {
i := With(1, 2, 3)

fmt.Println(At(i, -1))

// Output:
// 0 false
}

func ExampleAtKV() {
type tKV = KV[string, int]
i := WithKV(tKV{K: "a", V: 1}, tKV{K: "b", V: 2}, tKV{K: "c", V: 3})

fmt.Println(AtKV(i, 1))

// Output:
// b 2 true
}

func ExampleAtKV_outOfRange() {
type tKV = KV[string, int]
i := WithKV(tKV{K: "a", V: 1}, tKV{K: "b", V: 2})

fmt.Println(AtKV(i, 5))

// Output:
// 0 false
}

func ExampleAtKV_negative() {
type tKV = KV[string, int]
i := WithKV(tKV{K: "a", V: 1}, tKV{K: "b", V: 2})

fmt.Println(AtKV(i, -1))

// Output:
// 0 false
}

func ExampleAtKV_empty() {
i := WithKV[string, int]()

fmt.Println(AtKV(i, 0))

// Output:
// 0 false
}
func ExampleFind() {
i := With(1, 2, 3, 4, 5)

Expand Down
Loading