docs: lots of various doc improvements (#706)

This commit is contained in:
Samuel Berthe
2025-10-08 14:55:05 +02:00
committed by GitHub
parent fa2d72448a
commit c7e9459a8b
23 changed files with 478 additions and 59 deletions
+3 -2
View File
@@ -3,7 +3,6 @@
[![tag](https://img.shields.io/github/tag/samber/lo.svg)](https://github.com/samber/lo/releases)
![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.18-%23007d9c)
[![Doc](https://img.shields.io/badge/Official-doc-007d9c)](https://lo.samber.dev)
[![GoDoc](https://godoc.org/github.com/samber/lo?status.svg)](https://pkg.go.dev/github.com/samber/lo)
![Build Status](https://github.com/samber/lo/actions/workflows/test.yml/badge.svg)
[![Go report](https://goreportcard.com/badge/github.com/samber/lo)](https://goreportcard.com/report/github.com/samber/lo)
@@ -86,7 +85,9 @@ I take no responsibility for this junk. 😁 💩
## 🤠 Spec
GoDoc: [https://godoc.org/github.com/samber/lo](https://godoc.org/github.com/samber/lo)
GoDoc: [godoc.org/github.com/samber/lo](https://godoc.org/github.com/samber/lo)
Documentation: [lo.samber.dev](https://lo.samber.dev/docs/about)
Supported helpers for slices:
+23 -4
View File
@@ -21,7 +21,11 @@ signatures:
- "func SliceToMap[T any, K comparable, V any](collection []T, transform func(item T) (K, V)) map[K]V"
---
Builds a map from a slice using a transform that yields key/value for each item.
Builds a map from a slice using a transform function that yields key/value pairs for each item. Perfect for converting collections to lookup maps.
### Associate
Transforms each element into a key-value pair. Later items with the same key will overwrite earlier ones.
```go
type foo struct {
@@ -34,10 +38,12 @@ in := []*foo{{baz: "apple", bar: 1}, {baz: "banana", bar: 2}}
m := lo.Associate(in, func(f *foo) (string, int) {
return f.baz, f.bar
})
// map[string]int{"apple": 1, "banana": 2}
// m: map[string]int{"apple": 1, "banana": 2}
```
### With index
### AssociateI
Variant that includes the element index in the transform function, useful when you need the position in the original slice.
```go
type User struct {
@@ -53,5 +59,18 @@ users := []User{
result := lo.AssociateI(users, func(user User, index int) (string, int) {
return fmt.Sprintf("%s-%d", user.Name, index), user.Age
})
// map[string]int{"Alice-0": 25, "Bob-1": 30}
// result: map[string]int{"Alice-0": 25, "Bob-1": 30}
```
### SliceToMap
Alias for Associate - provides the same functionality with a more explicit name.
```go
products := []string{"apple", "banana", "cherry"}
result := lo.SliceToMap(products, func(product string) (string, int) {
return product, len(product)
})
// result: map[string]int{"apple": 5, "banana": 6, "cherry": 6}
```
+28 -3
View File
@@ -16,16 +16,41 @@ signatures:
- "func Attempt(maxIteration int, f func(index int) error) (int, error)"
---
Invokes a function up to N times until it returns nil. Returns the number of iterations and the last error.
Invokes a function up to N times until it returns nil. Returns the number of iterations attempted (1-based) and the last error. Useful for retrying operations that might fail temporarily.
```go
// Success after 3 attempts
iter, err := lo.Attempt(5, func(i int) error {
if i == 2 {
return nil
return nil // succeeds on 3rd attempt (index 2)
}
return errors.New("failed")
})
// 3, nil
// iter: 3, err: nil
```
```go
// All attempts fail - returns last error
iter, err = lo.Attempt(3, func(i int) error {
return fmt.Errorf("attempt %d failed", i)
})
// iter: 3, err: "attempt 2 failed" (last error from index 2)
```
```go
// Immediate success on first attempt
iter, err = lo.Attempt(5, func(i int) error {
return nil // succeeds immediately
})
// iter: 1, err: nil
```
```go
// Zero attempts - returns error without calling function
iter, err = lo.Attempt(0, func(i int) error {
return errors.New("should not be called")
})
// iter: 0, err: "maxIteration must be greater than 0"
```
+22 -2
View File
@@ -24,11 +24,31 @@ signatures:
- "func Map[T any, R any](collection []T, iteratee func(item T, index int) R) []R"
---
Manipulates a slice and transforms it to a slice of another type.
Transforms each element in a slice to a new type using a function. Takes both the element and its index, making it useful for transformations that need positional context.
```go
// Basic type transformation
transformed := lo.Map([]int64{1, 2, 3, 4}, func(x int64, index int) string {
return strconv.FormatInt(x, 10)
})
// []string{"1", "2", "3", "4"}
// transformed: []string{"1", "2", "3", "4"}
```
```go
// Transforming structs
type Person struct {
FirstName string
LastName string
Age int
}
people := []Person{
{FirstName: "John", LastName: "Doe", Age: 25},
{FirstName: "Jane", LastName: "Smith", Age: 30},
}
fullNames := lo.Map(people, func(p Person, index int) string {
return fmt.Sprintf("%s %s", p.FirstName, p.LastName)
})
// fullNames: []string{"John Doe", "Jane Smith"}
```
+25
View File
@@ -0,0 +1,25 @@
---
name: CountBy
slug: countby
sourceRef: it/seq.go#L325
category: it
subCategory: find
signatures:
- "func CountBy[T any](collection iter.Seq[T], predicate func(item T) bool) int"
playUrl:
variantHelpers:
- it#find#count
similarHelpers:
- core#slice#countby
- core#slice#count
position: 35
---
Counts the number of elements in the collection that satisfy the predicate.
```go
result := it.CountBy(it.Range(1, 11), func(item int) bool {
return item%2 == 0
})
// 5
```
+23
View File
@@ -0,0 +1,23 @@
---
name: DropByIndex
slug: dropbyindex
sourceRef: it/seq.go#L581
category: it
subCategory: sequence
signatures:
- "func DropByIndex[T any, I ~func(func(T) bool)](collection I, indexes ...int) I"
playUrl:
variantHelpers:
- it#slice#drop
similarHelpers:
- core#slice#dropbyindex
- core#slice#withoutnth
position: 55
---
Removes elements from a collection at the specified indexes.
```go
result := it.DropByIndex(it.Range(1, 6), 1, 3)
// [1, 3, 5]
```
+18 -1
View File
@@ -6,19 +6,21 @@ category: it
subCategory: sequence
signatures:
- "func Filter[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I"
- "func FilterI[T any, I ~func(func(T) bool)](collection I, predicate func(item T, index int) bool) I"
playUrl: ""
variantHelpers:
- it#sequence#filter
- it#sequence#filteri
similarHelpers:
- core#slice#filter
- core#slice#filteri
- it#sequence#reject
position: 10
---
Returns a sequence of all elements for which the predicate function returns true.
Examples:
### Filter
```go
seq := func(yield func(int) bool) {
@@ -36,4 +38,19 @@ for v := range filtered {
result = append(result, v)
}
// result contains 2, 4 (even numbers)
```
### FilterI
FilterI iterates over elements of collection, returning a sequence of all elements predicate returns true for. The predicate function includes the index.
```go
result := it.FilterI(it.Range(1, 6), func(item int, index int) bool {
return item%2 == 0 && index > 1
})
var filtered []int
for v := range result {
filtered = append(filtered, v)
}
// filtered contains [4, 6]
```
+29
View File
@@ -0,0 +1,29 @@
---
name: FromPairs
slug: frompairs
sourceRef: it/map.go#L104
category: it
subCategory: map
signatures:
- "func FromPairs[K comparable, V any](entries ...iter.Seq2[K, V]) map[K]V"
playUrl:
variantHelpers:
- it#map#fromentries
similarHelpers:
- core#slice#frompairs
- core#slice#fromentries
position: 20
---
Transforms a sequence of key/value pairs into a map. Alias of FromEntries().
```go
pairs := it.Seq2(func(yield func(string, int) bool) {
yield("a", 1)
yield("b", 2)
yield("c", 3)
})
result := it.FromPairs(pairs)
// map[string]int{"a": 1, "b": 2, "c": 3}
```
+14 -5
View File
@@ -15,11 +15,10 @@ similarHelpers:
position: 0
---
Returns the index at which the first occurrence of a value is found in the sequence, or -1 if the value is not found.
Examples:
Returns the index at which the first occurrence of a value is found in the sequence, or -1 if the value is not found. Scans the sequence from the beginning and returns the position of the first matching element.
```go
// Find existing element - returns first occurrence
seq := func(yield func(int) bool) {
_ = yield(10)
_ = yield(20)
@@ -27,15 +26,25 @@ seq := func(yield func(int) bool) {
_ = yield(20)
}
idx := it.IndexOf(seq, 20)
// idx == 1
// idx: 1 (first occurrence of 20)
```
```go
// Element not found - returns -1
seq := func(yield func(string) bool) {
_ = yield("apple")
_ = yield("banana")
_ = yield("cherry")
}
idx := it.IndexOf(seq, "orange")
// idx == -1
// idx: -1 (orange not found in sequence)
```
```go
// Empty sequence - returns -1
emptySeq := func(yield func(string) bool) {
// no elements yielded
}
idx := it.IndexOf(emptySeq, "anything")
// idx: -1 (sequence is empty)
```
+26
View File
@@ -0,0 +1,26 @@
---
name: IsNotEmpty
slug: isnotempty
sourceRef: it/type_manipulation.go#L59
category: it
subCategory: condition
signatures:
- "func IsNotEmpty[T any](collection iter.Seq[T]) bool"
playUrl:
variantHelpers:
- it#condition#isempty
similarHelpers:
- core#slice#isnotempty
- core#slice#isempty
position: 10
---
Returns true if the collection is not empty, false otherwise.
```go
result1 := it.IsNotEmpty(it.Range(1, 5))
// true
result2 := it.IsNotEmpty(it.Empty[int]())
// false
```
+25
View File
@@ -0,0 +1,25 @@
---
name: KeyBy
slug: keyby
sourceRef: it/seq.go#L398
category: it
subCategory: sequence
signatures:
- "func KeyBy[K comparable, V any](collection iter.Seq[V], transform func(item V) K) map[K]V"
playUrl:
variantHelpers:
- it#map#associate
similarHelpers:
- core#slice#keyby
- core#slice#associate
position: 15
---
Transforms a sequence into a map using a transform function to generate keys.
```go
result := it.KeyBy(it.Range(1, 5), func(item int) string {
return fmt.Sprintf("key-%d", item)
})
// map[string]int{"key-1": 1, "key-2": 2, "key-3": 3, "key-4": 4}
```
+1 -1
View File
@@ -56,4 +56,4 @@ for v := range mapped {
result = append(result, v)
}
// result contains "item-10-0", "item-20-1", "item-30-2"
```
```
+36
View File
@@ -0,0 +1,36 @@
---
name: MeanBy
slug: meanby
sourceRef: it/math.go#L106
category: it
subCategory: math
signatures:
- "func MeanBy[T any, R constraints.Float | constraints.Integer](collection iter.Seq[T], transform func(item T) R) R"
playUrl:
variantHelpers:
- it#math#mean
similarHelpers:
- core#slice#meanby
- core#slice#mean
position: 70
---
Returns the mean value of the collection using the given transform function.
```go
type Person struct {
Name string
Age int
}
people := it.Slice([]Person{
{"Alice", 25},
{"Bob", 30},
{"Charlie", 35},
})
result := it.MeanBy(people, func(p Person) int {
return p.Age
})
// 30.0
```
+25
View File
@@ -0,0 +1,25 @@
---
name: ProductBy
slug: productby
sourceRef: it/math.go#L90
category: it
subCategory: math
signatures:
- "func ProductBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T], transform func(item T) R) R"
playUrl:
variantHelpers:
- it#math#product
similarHelpers:
- core#slice#productby
- core#slice#product
position: 67
---
Returns the product of values in the collection using the given transform function.
```go
result := it.ProductBy(it.Range(1, 5), func(item int) int {
return item * 2
})
// 384 (2 * 4 * 6 * 8)
```
+9 -34
View File
@@ -6,23 +6,21 @@ category: it
subCategory: sequence
signatures:
- "func Reduce[T, R any](collection iter.Seq[T], accumulator func(agg R, item T) R, initial R) R"
- "func ReduceLast[T, R any](collection iter.Seq[T], accumulator func(agg R, item T) R, initial R) R"
- "func ReduceLastI[T, R any](collection iter.Seq[T], accumulator func(agg R, item T, index int) R, initial R) R"
- "func ReduceI[T, R any](collection iter.Seq[T], accumulator func(agg R, item T, index int) R, initial R) R"
playUrl: ""
variantHelpers:
- it#sequence#reduce
- it#sequence#reducei
- it#sequence#reducelast
- it#sequence#reducelasti
similarHelpers:
- core#slice#reduce
- core#slice#reducei
- core#slice#reduceright
position: 30
---
Reduces a collection to a single accumulated value by applying an accumulator function to each element starting with an initial value.
Examples:
### Reduce
```go
seq := func(yield func(int) bool) {
@@ -48,36 +46,13 @@ concat := it.Reduce(seq, func(acc string, item string) string {
// concat == " hello world"
```
ReduceLast is like Reduce except that it iterates over elements of collection in reverse.
### ReduceI
Reduces a collection to a single value by iterating through elements and applying an accumulator function that includes the index.
```go
seq := func(yield func(int) bool) {
_ = yield(1)
_ = yield(2)
_ = yield(3)
_ = yield(4)
}
sum := it.ReduceLast(seq, func(acc int, item int) int {
return acc + item
result := it.ReduceI(it.Range(1, 5), func(agg int, item int, index int) int {
return agg + item*index
}, 0)
// sum == 10 (4 + 3 + 2 + 1 + 0)
result := it.ReduceLast(seq, func(agg string, item int) string {
return fmt.Sprintf("%d-%s", item, agg)
}, "end")
// result == "4-3-2-1-end"
```
ReduceLastI is like Reduce except that it iterates over elements of collection in reverse, with index.
```go
seq := func(yield func(string) bool) {
_ = yield("a")
_ = yield("b")
_ = yield("c")
}
result := it.ReduceLastI(seq, func(agg string, item string, index int) string {
return fmt.Sprintf("%s:%d:%s", agg, index, item)
}, "start")
// result == "start:2:c:1:b:0:a"
// 20 (0*0 + 1*1 + 2*2 + 3*3)
```
+43
View File
@@ -0,0 +1,43 @@
---
name: ReduceLast
slug: reducelast
sourceRef: it/seq.go#L153
category: it
subCategory: sequence
signatures:
- "func ReduceLast[T, R any](collection iter.Seq[T], accumulator func(agg R, item T) R, initial R) R"
- "func ReduceLastI[T, R any](collection iter.Seq[T], accumulator func(agg R, item T, index int) R, initial R) R"
playUrl:
variantHelpers:
- it#sequence#reduce
- it#sequence#reducei
- it#sequence#reducelast
- it#sequence#reducelasti
similarHelpers:
- core#slice#reducelast
- core#slice#reducelasti
- core#slice#reduce
position: 54
---
Reduces a collection from right to left, returning a single value.
### ReduceLast
```go
result := it.ReduceLast(it.Range(1, 5), func(agg int, item int) int {
return agg - item
}, 0)
// -10 (0 - 4 - 3 - 2 - 1)
```
### ReduceLastI
Reduces a collection from right to left, returning a single value. The accumulator function includes the index.
```go
result := it.ReduceLastI(it.Range(1, 5), func(agg int, item int, index int) int {
return agg - item*index
}, 0)
// -20 (0 - 4*3 - 3*2 - 2*1 - 1*0)
```
+23
View File
@@ -0,0 +1,23 @@
---
name: Repeat
slug: repeat
sourceRef: it/seq.go#L384
category: it
subCategory: sequence
signatures:
- "func Repeat[T lo.Clonable[T]](count int, initial T) iter.Seq[T]"
playUrl:
variantHelpers:
- it#slice#repeatby
similarHelpers:
- core#slice#repeat
- core#slice#repeatby
position: 75
---
Creates a sequence that repeats the initial value count times.
```go
result := it.Repeat(3, "hello")
// ["hello", "hello", "hello"]
```
+23
View File
@@ -0,0 +1,23 @@
---
name: Slice
slug: slice
sourceRef: it/seq.go#L680
category: it
subCategory: sequence
signatures:
- "func Slice[T any, I ~func(func(T) bool)](collection I, start, end int) I"
playUrl:
variantHelpers:
- it#slice#drop
similarHelpers:
- core#slice#slice
- core#slice#chunk
position: 80
---
Returns a sub-sequence from start index to end index (exclusive).
```go
result := it.Slice(it.Range(1, 10), 2, 5)
// [3, 4, 5]
```
+36
View File
@@ -0,0 +1,36 @@
---
name: SumBy
slug: sumby
sourceRef: it/math.go#L74
category: it
subCategory: math
signatures:
- "func SumBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T], transform func(item T) R) R"
playUrl:
variantHelpers:
- it#math#sumby
similarHelpers:
- core#slice#sumby
- core#slice#sum
position: 65
---
Returns the sum of values in the collection using the given transform function.
```go
type Person struct {
Name string
Age int
}
people := it.Slice([]Person{
{"Alice", 25},
{"Bob", 30},
{"Charlie", 35},
})
result := it.SumBy(people, func(p Person) int {
return p.Age
})
// 90
```
+25
View File
@@ -0,0 +1,25 @@
---
name: UniqBy
slug: uniqby
sourceRef: it/seq.go#L225
category: it
subCategory: sequence
signatures:
- "func UniqBy[T any, U comparable, I ~func(func(T) bool)](collection I, transform func(item T) U) I"
playUrl:
variantHelpers:
- it#slice#uniq
similarHelpers:
- core#slice#uniqby
- core#slice#uniq
position: 45
---
Returns a sequence with duplicate elements removed based on a transform function.
```go
result := it.UniqBy(it.Range(1, 7), func(item int) int {
return item % 3
})
// [1, 2, 3]
```
+10
View File
@@ -242,8 +242,14 @@ const config: Config = {
label: 'Changelog',
position: 'right',
},
{
to: 'https://github.com/sponsors/samber',
label: '💖 Sponsor',
position: 'right',
},
{
href: 'https://github.com/samber/lo',
label: 'GitHub',
position: 'right',
className: 'header-github-link',
'aria-label': 'GitHub repository',
@@ -276,6 +282,10 @@ const config: Config = {
label: 'License',
to: 'https://github.com/samber/ro/blob/master/LICENSE',
},
{
label: '💖 Sponsor',
to: 'https://github.com/sponsors/samber',
},
],
},
{
@@ -89,14 +89,18 @@ export default function HelperCard({
return elements;
}, [helper.content]);
const signatures = useMemo(() => {
return helper.signatures.join('\n');
}, [helper.signatures]);
// Post-process prototype code to colorize generic type parameters locally
const prototypeRowRef = useRef<HTMLDivElement>(null);
useEffect(() => {
// Ensure highlighting even if Prism updates asynchronously
const raf = requestAnimationFrame(() => {
ensurePrototypeGenericsHighlighted(prototypeRowRef.current as unknown as HTMLElement);
});
return () => cancelAnimationFrame(raf);
// // Ensure highlighting even if Prism updates asynchronously
// const raf = requestAnimationFrame(() => {
// ensurePrototypeGenericsHighlighted(prototypeRowRef.current as unknown as HTMLElement);
// });
// return () => cancelAnimationFrame(raf);
}, [helper.signatures]);
return (
@@ -177,7 +181,7 @@ export default function HelperCard({
<div className="helper-card__prototype">
<div className="helper-card__prototype-row" ref={prototypeRowRef}>
<span className="helper-card__prototype-label">Prototype{helper.signatures.length > 1 ? 's' : ''}:</span>
<CodeBlock language="go" className="helper-card__prototype-code" children={helper.signatures.join('\n')} />
<CodeBlock language="go" className="helper-card__prototype-code" children={signatures} />
</div>
</div>
</div>
+1 -1
View File
@@ -20,7 +20,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: '🧢 Core',
collapsible: true,
collapsible: false,
collapsed: false,
items: [
{type: 'autogenerated', dirName: 'core'},