mirror of
https://github.com/samber/lo.git
synced 2025-09-26 20:11:13 +08:00
doc: adding go playground examples
This commit is contained in:
77
README.md
77
README.md
@@ -392,6 +392,8 @@ lop.Map([]int64{1, 2, 3, 4}, func(x int64, _ int) string {
|
||||
// []string{"1", "2", "3", "4"}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/sCJaB3quRMC)]
|
||||
|
||||
Mutable: like `lo.Map()`, but the slice is updated in place.
|
||||
|
||||
```go
|
||||
@@ -404,6 +406,8 @@ lom.Map(list, func(x int) int {
|
||||
// []int{2, 4, 6, 8}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/0jY3Z0B7O_5)]
|
||||
|
||||
### UniqMap
|
||||
|
||||
Manipulates a slice and transforms it to a slice of another type with unique values.
|
||||
@@ -421,6 +425,8 @@ names := lo.UniqMap(users, func(u User, index int) string {
|
||||
// []string{"Alex", "Bob", "Alice"}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/fygzLBhvUdB)]
|
||||
|
||||
### FilterMap
|
||||
|
||||
Returns a slice which obtained after both filtering and mapping using the given callback function.
|
||||
@@ -616,6 +622,8 @@ groups := lo.GroupByMap([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, int) {
|
||||
// map[int][]int{0: []int{0, 6}, 1: []int{2, 8}, 2: []int{4, 10}}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/iMeruQ3_W80)]
|
||||
|
||||
### Chunk
|
||||
|
||||
Returns an array of elements split into groups the length of size. If array can't be split evenly, the final chunk will be the remaining elements.
|
||||
@@ -634,7 +642,7 @@ lo.Chunk([]int{0}, 2)
|
||||
// [][]int{{0}}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/EeKl0AuTehH)]
|
||||
[[play](https://go.dev/play/p/kEMkFbdu85g)]
|
||||
|
||||
### PartitionBy
|
||||
|
||||
@@ -853,6 +861,8 @@ result := lo.FilterSliceToMap(list, func(str string) (string, int, bool) {
|
||||
// map[string][int]{"aa":2 "aaa":3}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/2z0rDz2ZSGU)]
|
||||
|
||||
### Keyify
|
||||
|
||||
Returns a map with each unique element of the slice as a key.
|
||||
@@ -862,6 +872,8 @@ set := lo.Keyify([]int{1, 1, 2, 3, 4})
|
||||
// map[int]struct{}{1:{}, 2:{}, 3:{}, 4:{}}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/RYhhM_csqIG)]
|
||||
|
||||
### Drop
|
||||
|
||||
Drops n elements from the beginning of a slice or array.
|
||||
@@ -1360,7 +1372,7 @@ entries := lo.Entries(map[string]int{"foo": 1, "bar": 2})
|
||||
// }
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/3Dhgx46gawJ)]
|
||||
[[play](https://go.dev/play/p/_t4Xe34-Nl5)]
|
||||
|
||||
### FromEntries (alias: FromPairs)
|
||||
|
||||
@@ -1678,6 +1690,8 @@ mean := lo.MeanBy([]float64{}, mapper)
|
||||
// 0
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/j7TsVwBOZ7P)]
|
||||
|
||||
|
||||
### Mode
|
||||
|
||||
@@ -1773,7 +1787,7 @@ str := lo.PascalCase("hello_world")
|
||||
// HelloWorld
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/iZkdeLP9oiB)]
|
||||
[[play](https://go.dev/play/p/Dy_V_6DUYhe)]
|
||||
|
||||
### CamelCase
|
||||
|
||||
@@ -1784,7 +1798,7 @@ str := lo.CamelCase("hello_world")
|
||||
// helloWorld
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/dtyFB58MBRp)]
|
||||
[[play](https://go.dev/play/p/Go6aKwUiq59)]
|
||||
|
||||
### KebabCase
|
||||
|
||||
@@ -1795,7 +1809,7 @@ str := lo.KebabCase("helloWorld")
|
||||
// hello-world
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/2YTuPafwECA)]
|
||||
[[play](https://go.dev/play/p/96gT_WZnTVP)]
|
||||
|
||||
### SnakeCase
|
||||
|
||||
@@ -1806,7 +1820,7 @@ str := lo.SnakeCase("HelloWorld")
|
||||
// hello_world
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/QVKJG9nOnDg)]
|
||||
[[play](https://go.dev/play/p/ziB0V89IeVH)]
|
||||
|
||||
### Words
|
||||
|
||||
@@ -1817,7 +1831,7 @@ str := lo.Words("helloWorld")
|
||||
// []string{"hello", "world"}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/2P4zhqqq61g)]
|
||||
[[play](https://go.dev/play/p/-f3VIQqiaVw)]
|
||||
|
||||
### Capitalize
|
||||
|
||||
@@ -1828,6 +1842,8 @@ str := lo.Capitalize("heLLO")
|
||||
// Hello
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/uLTZZQXqnsa)]
|
||||
|
||||
### Ellipsis
|
||||
|
||||
Trims and truncates a string to a specified length in `bytes` and appends an ellipsis if truncated. If the string contains non-ASCII characters (which may occupy multiple bytes in UTF-8), truncating by byte length may split a character in the middle, potentially resulting in garbled output.
|
||||
@@ -1843,6 +1859,8 @@ str := lo.Ellipsis("Lorem Ipsum", 3)
|
||||
// ...
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/qE93rgqe1TW)]
|
||||
|
||||
### T2 -> T9
|
||||
|
||||
Creates a tuple from a list of values.
|
||||
@@ -1968,6 +1986,8 @@ duration := lo.Duration(func() {
|
||||
// 3s
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/HQfbBbAXaFP)]
|
||||
|
||||
### Duration0 -> Duration10
|
||||
|
||||
Returns the time taken to execute a function.
|
||||
@@ -2028,6 +2048,8 @@ for i := range children {
|
||||
}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/UZGu2wVg3J2)]
|
||||
|
||||
Many distributions strategies are available:
|
||||
|
||||
- [lo.DispatchingStrategyRoundRobin](./channel.go): Distributes messages in a rotating sequential manner.
|
||||
@@ -2088,6 +2110,8 @@ for v := range lo.SliceToChannel(2, list) {
|
||||
// prints 1, then 2, then 3, then 4, then 5
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/lIbSY3QmiEg)]
|
||||
|
||||
### ChannelToSlice
|
||||
|
||||
Returns a slice built from channels items. Blocks until channel closes.
|
||||
@@ -2274,6 +2298,8 @@ present := lo.Contains([]int{0, 1, 2, 3, 4, 5}, 5)
|
||||
// true
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/W1EvyqY6t9j)]
|
||||
|
||||
### ContainsBy
|
||||
|
||||
Returns true if the predicate function returns `true`.
|
||||
@@ -2308,6 +2334,8 @@ b := EveryBy([]int{1, 2, 3, 4}, func(x int) bool {
|
||||
// true
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/dn1-vhHsq9x)]
|
||||
|
||||
### Some
|
||||
|
||||
Returns true if at least 1 element of a subset is contained into a collection.
|
||||
@@ -2316,6 +2344,9 @@ If the subset is empty Some returns false.
|
||||
```go
|
||||
ok := lo.Some([]int{0, 1, 2, 3, 4, 5}, []int{0, 6})
|
||||
// true
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/Lj4ceFkeT9V)]
|
||||
|
||||
ok := lo.Some([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})
|
||||
// false
|
||||
@@ -2344,6 +2375,8 @@ b := None([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})
|
||||
// true
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/fye7JsmxzPV)]
|
||||
|
||||
### NoneBy
|
||||
|
||||
Returns true if the predicate returns true for none of the elements in the collection or if the collection is empty.
|
||||
@@ -2355,6 +2388,8 @@ b := NoneBy([]int{1, 2, 3, 4}, func(x int) bool {
|
||||
// true
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/O64WZ32H58S)]
|
||||
|
||||
### Intersect
|
||||
|
||||
Returns the intersection between two collections.
|
||||
@@ -2385,6 +2420,8 @@ left, right := lo.Difference([]int{0, 1, 2, 3, 4, 5}, []int{0, 1, 2, 3, 4, 5})
|
||||
// []int{}, []int{}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/pKE-JgzqRpz)]
|
||||
|
||||
### Union
|
||||
|
||||
Returns all distinct elements from given collections. Result will not change the order of elements relatively.
|
||||
@@ -2499,6 +2536,8 @@ notFound := lo.IndexOf([]int{0, 1, 2, 1, 2, 3}, 6)
|
||||
// -1
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/Eo7W0lvKTky)]
|
||||
|
||||
### LastIndexOf
|
||||
|
||||
Returns the index at which the last occurrence of a value is found in an array or return -1 if the value cannot be found.
|
||||
@@ -2527,6 +2566,8 @@ str, ok := lo.Find([]string{"foobar"}, func(i string) bool {
|
||||
// "", false
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/Eo7W0lvKTky)]
|
||||
|
||||
### FindIndexOf
|
||||
|
||||
FindIndexOf searches an element in a slice based on a predicate and returns the index and true. It returns -1 and false if the element is not found.
|
||||
@@ -2543,6 +2584,8 @@ str, index, ok := lo.FindIndexOf([]string{"foobar"}, func(i string) bool {
|
||||
// "", -1, false
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/XWSEM4Ic_t0)]
|
||||
|
||||
### FindLastIndexOf
|
||||
|
||||
FindLastIndexOf searches an element in a slice based on a predicate and returns the index and true. It returns -1 and false if the element is not found.
|
||||
@@ -2559,6 +2602,8 @@ str, index, ok := lo.FindLastIndexOf([]string{"foobar"}, func(i string) bool {
|
||||
// "", -1, false
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/dPiMRtJ6cUx)]
|
||||
|
||||
### FindOrElse
|
||||
|
||||
Search an element in a slice based on a predicate. It returns the element if found or a given fallback value otherwise.
|
||||
@@ -2666,6 +2711,8 @@ min := lo.Min([]time.Duration{time.Second, time.Hour})
|
||||
// 1s
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/r6e-Z8JozS8)]
|
||||
|
||||
### MinIndex
|
||||
|
||||
Search the minimum value of a collection and the index of the minimum value.
|
||||
@@ -2985,6 +3032,8 @@ lo.Sample([]string{})
|
||||
// ""
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/FYA45LcpfM2)]
|
||||
|
||||
|
||||
|
||||
### SampleBy
|
||||
@@ -3215,6 +3264,8 @@ ptr := lo.ToPtr("hello world")
|
||||
// *string{"hello world"}
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/P2sD0PMXw4F)]
|
||||
|
||||
### Nil
|
||||
|
||||
Returns a nil pointer of type.
|
||||
@@ -3503,6 +3554,8 @@ f(42)
|
||||
// 47
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/Sy1gAQiQZ3v)]
|
||||
|
||||
### Partial2 -> Partial5
|
||||
|
||||
Returns new function that, when called, has its first argument set to the provided value.
|
||||
@@ -3518,6 +3571,8 @@ f(42, -4)
|
||||
// 80
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/-xiPjy4JChJ)]
|
||||
|
||||
### Attempt
|
||||
|
||||
Invokes a function N times until it returns valid output. Returns either the caught error or nil.
|
||||
@@ -3606,7 +3661,7 @@ count1, err1 := lo.AttemptWhile(5, func(i int) (error, bool) {
|
||||
|
||||
For more advanced retry strategies (delay, exponential backoff...), please take a look on [cenkalti/backoff](https://github.com/cenkalti/backoff).
|
||||
|
||||
[[play](https://go.dev/play/p/M2wVq24PaZM)]
|
||||
[[play](https://go.dev/play/p/1VS7HxlYMOG)]
|
||||
|
||||
### AttemptWhileWithDelay
|
||||
|
||||
@@ -3631,7 +3686,7 @@ count1, time1, err1 := lo.AttemptWhileWithDelay(5, time.Millisecond, func(i int,
|
||||
|
||||
For more advanced retry strategies (delay, exponential backoff...), please take a look on [cenkalti/backoff](https://github.com/cenkalti/backoff).
|
||||
|
||||
[[play](https://go.dev/play/p/cfcmhvLO-nv)]
|
||||
[[play](https://go.dev/play/p/mhufUjJfLEF)]
|
||||
|
||||
### Debounce
|
||||
|
||||
@@ -3876,6 +3931,8 @@ iterations, duration, ok := lo.WaitFor(laterTrue, 10*time.Millisecond, 5*time.Mi
|
||||
// false
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/t_wTDmubbK3)]
|
||||
|
||||
### WaitForWithContext
|
||||
|
||||
Runs periodically until a condition is validated or context is invalid.
|
||||
@@ -3918,6 +3975,8 @@ iterations, duration, ok := lo.WaitForWithContext(expiringCtx, alwaysFalse, 100*
|
||||
// false
|
||||
```
|
||||
|
||||
[[play](https://go.dev/play/p/t_wTDmubbK3)]
|
||||
|
||||
### Validate
|
||||
|
||||
Helper function that creates an error when a condition is not met.
|
||||
|
15
channel.go
15
channel.go
@@ -14,6 +14,7 @@ type DispatchingStrategy[T any] func(msg T, index uint64, channels []<-chan T) i
|
||||
// ChannelDispatcher distributes messages from input channels into N child channels.
|
||||
// Close events are propagated to children.
|
||||
// Underlying channels can have a fixed buffer capacity or be unbuffered when cap is 0.
|
||||
// Play: https://go.dev/play/p/UZGu2wVg3J2
|
||||
func ChannelDispatcher[T any](stream <-chan T, count int, channelBufferCap int, strategy DispatchingStrategy[T]) []<-chan T {
|
||||
children := createChannels[T](count, channelBufferCap)
|
||||
|
||||
@@ -73,6 +74,7 @@ func channelIsNotFull[T any](ch <-chan T) bool {
|
||||
|
||||
// DispatchingStrategyRoundRobin distributes messages in a rotating sequential manner.
|
||||
// If the channel capacity is exceeded, the next channel will be selected and so on.
|
||||
// Play: https://go.dev/play/p/UZGu2wVg3J2
|
||||
func DispatchingStrategyRoundRobin[T any](msg T, index uint64, channels []<-chan T) int {
|
||||
for {
|
||||
i := int(index % uint64(len(channels)))
|
||||
@@ -87,6 +89,7 @@ func DispatchingStrategyRoundRobin[T any](msg T, index uint64, channels []<-chan
|
||||
|
||||
// DispatchingStrategyRandom distributes messages in a random manner.
|
||||
// If the channel capacity is exceeded, another random channel will be selected and so on.
|
||||
// Play: https://go.dev/play/p/GEyGn3TdGk4
|
||||
func DispatchingStrategyRandom[T any](msg T, index uint64, channels []<-chan T) int {
|
||||
for {
|
||||
i := rand.IntN(len(channels))
|
||||
@@ -100,6 +103,7 @@ func DispatchingStrategyRandom[T any](msg T, index uint64, channels []<-chan T)
|
||||
|
||||
// DispatchingStrategyWeightedRandom distributes messages in a weighted manner.
|
||||
// If the channel capacity is exceeded, another random channel will be selected and so on.
|
||||
// Play: https://go.dev/play/p/v0eMh8NZG2L
|
||||
func DispatchingStrategyWeightedRandom[T any](weights []int) DispatchingStrategy[T] {
|
||||
seq := []int{}
|
||||
|
||||
@@ -123,6 +127,7 @@ func DispatchingStrategyWeightedRandom[T any](weights []int) DispatchingStrategy
|
||||
|
||||
// DispatchingStrategyFirst distributes messages in the first non-full channel.
|
||||
// If the capacity of the first channel is exceeded, the second channel will be selected and so on.
|
||||
// Play: https://go.dev/play/p/OrJCvOmk42f
|
||||
func DispatchingStrategyFirst[T any](msg T, index uint64, channels []<-chan T) int {
|
||||
for {
|
||||
for i := range channels {
|
||||
@@ -136,6 +141,7 @@ func DispatchingStrategyFirst[T any](msg T, index uint64, channels []<-chan T) i
|
||||
}
|
||||
|
||||
// DispatchingStrategyLeast distributes messages in the emptiest channel.
|
||||
// Play: https://go.dev/play/p/ypy0jrRcEe7
|
||||
func DispatchingStrategyLeast[T any](msg T, index uint64, channels []<-chan T) int {
|
||||
seq := Range(len(channels))
|
||||
|
||||
@@ -146,6 +152,7 @@ func DispatchingStrategyLeast[T any](msg T, index uint64, channels []<-chan T) i
|
||||
|
||||
// DispatchingStrategyMost distributes messages in the fullest channel.
|
||||
// If the channel capacity is exceeded, the next channel will be selected and so on.
|
||||
// Play: https://go.dev/play/p/erHHone7rF9
|
||||
func DispatchingStrategyMost[T any](msg T, index uint64, channels []<-chan T) int {
|
||||
seq := Range(len(channels))
|
||||
|
||||
@@ -155,6 +162,7 @@ func DispatchingStrategyMost[T any](msg T, index uint64, channels []<-chan T) in
|
||||
}
|
||||
|
||||
// SliceToChannel returns a read-only channels of collection elements.
|
||||
// Play: https://go.dev/play/p/lIbSY3QmiEg
|
||||
func SliceToChannel[T any](bufferSize int, collection []T) <-chan T {
|
||||
ch := make(chan T, bufferSize)
|
||||
|
||||
@@ -170,6 +178,7 @@ func SliceToChannel[T any](bufferSize int, collection []T) <-chan T {
|
||||
}
|
||||
|
||||
// ChannelToSlice returns a slice built from channels items. Blocks until channel closes.
|
||||
// Play: https://go.dev/play/p/lIbSY3QmiEg
|
||||
func ChannelToSlice[T any](ch <-chan T) []T {
|
||||
collection := []T{}
|
||||
|
||||
@@ -181,6 +190,7 @@ func ChannelToSlice[T any](ch <-chan T) []T {
|
||||
}
|
||||
|
||||
// Generator implements the generator design pattern.
|
||||
// Play: https://go.dev/play/p/lIbSY3QmiEg
|
||||
func Generator[T any](bufferSize int, generator func(yield func(T))) <-chan T {
|
||||
ch := make(chan T, bufferSize)
|
||||
|
||||
@@ -198,6 +208,7 @@ func Generator[T any](bufferSize int, generator func(yield func(T))) <-chan T {
|
||||
|
||||
// Buffer creates a slice of n elements from a channel. Returns the slice and the slice length.
|
||||
// @TODO: we should probably provide an helper that reuse the same buffer.
|
||||
// Play: https://go.dev/play/p/gPQ-6xmcKQI
|
||||
func Buffer[T any](ch <-chan T, size int) (collection []T, length int, readTime time.Duration, ok bool) {
|
||||
buffer := make([]T, 0, size)
|
||||
index := 0
|
||||
@@ -224,6 +235,7 @@ func Batch[T any](ch <-chan T, size int) (collection []T, length int, readTime t
|
||||
|
||||
// BufferWithContext creates a slice of n elements from a channel, with context. Returns the slice and the slice length.
|
||||
// @TODO: we should probably provide an helper that reuse the same buffer.
|
||||
// Play: https://go.dev/play/p/oRfOyJWK9YF
|
||||
func BufferWithContext[T any](ctx context.Context, ch <-chan T, size int) (collection []T, length int, readTime time.Duration, ok bool) {
|
||||
buffer := make([]T, 0, size)
|
||||
now := time.Now()
|
||||
@@ -246,6 +258,7 @@ func BufferWithContext[T any](ctx context.Context, ch <-chan T, size int) (colle
|
||||
}
|
||||
|
||||
// BufferWithTimeout creates a slice of n elements from a channel, with timeout. Returns the slice and the slice length.
|
||||
// Play: https://go.dev/play/p/sxyEM3koo4n
|
||||
func BufferWithTimeout[T any](ch <-chan T, size int, timeout time.Duration) (collection []T, length int, readTime time.Duration, ok bool) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
@@ -261,6 +274,7 @@ func BatchWithTimeout[T any](ch <-chan T, size int, timeout time.Duration) (coll
|
||||
|
||||
// FanIn collects messages from multiple input channels into a single buffered channel.
|
||||
// Output messages has no priority. When all upstream channels reach EOF, downstream channel closes.
|
||||
// Play: https://go.dev/play/p/FH8Wq-T04Jb
|
||||
func FanIn[T any](channelBufferCap int, upstreams ...<-chan T) <-chan T {
|
||||
out := make(chan T, channelBufferCap)
|
||||
var wg sync.WaitGroup
|
||||
@@ -295,6 +309,7 @@ func ChannelMerge[T any](channelBufferCap int, upstreams ...<-chan T) <-chan T {
|
||||
// FanOut broadcasts all the upstream messages to multiple downstream channels.
|
||||
// When upstream channel reach EOF, downstream channels close. If any downstream
|
||||
// channels is full, broadcasting is paused.
|
||||
// Play: https://go.dev/play/p/2LHxcjKX23L
|
||||
func FanOut[T any](count int, channelsBufferCap int, upstream <-chan T) []<-chan T {
|
||||
downstreams := createChannels[T](count, channelsBufferCap)
|
||||
|
||||
|
@@ -17,6 +17,7 @@ func (s *synchronize) Do(cb func()) {
|
||||
}
|
||||
|
||||
// Synchronize wraps the underlying callback in a mutex. It receives an optional mutex.
|
||||
// Play: https://go.dev/play/p/X3cqROSpQmu
|
||||
func Synchronize(opt ...sync.Locker) *synchronize { //nolint:revive
|
||||
if len(opt) > 1 {
|
||||
panic("unexpected arguments")
|
||||
@@ -30,6 +31,7 @@ func Synchronize(opt ...sync.Locker) *synchronize { //nolint:revive
|
||||
}
|
||||
|
||||
// Async executes a function in a goroutine and returns the result in a channel.
|
||||
// Play: https://go.dev/play/p/uo35gosuTLw
|
||||
func Async[A any](f func() A) <-chan A {
|
||||
ch := make(chan A, 1)
|
||||
go func() {
|
||||
@@ -39,6 +41,7 @@ func Async[A any](f func() A) <-chan A {
|
||||
}
|
||||
|
||||
// Async0 executes a function in a goroutine and returns a channel set once the function finishes.
|
||||
// Play: https://go.dev/play/p/tNqf1cClG_o
|
||||
func Async0(f func()) <-chan struct{} {
|
||||
ch := make(chan struct{}, 1)
|
||||
go func() {
|
||||
@@ -49,11 +52,13 @@ func Async0(f func()) <-chan struct{} {
|
||||
}
|
||||
|
||||
// Async1 is an alias to Async.
|
||||
// Play: https://go.dev/play/p/uo35gosuTLw
|
||||
func Async1[A any](f func() A) <-chan A {
|
||||
return Async(f)
|
||||
}
|
||||
|
||||
// Async2 has the same behavior as Async, but returns the 2 results as a tuple inside the channel.
|
||||
// Play: https://go.dev/play/p/7W7mKQi0AhA
|
||||
func Async2[A, B any](f func() (A, B)) <-chan Tuple2[A, B] {
|
||||
ch := make(chan Tuple2[A, B], 1)
|
||||
go func() {
|
||||
@@ -63,6 +68,7 @@ func Async2[A, B any](f func() (A, B)) <-chan Tuple2[A, B] {
|
||||
}
|
||||
|
||||
// Async3 has the same behavior as Async, but returns the 3 results as a tuple inside the channel.
|
||||
// Play: https://go.dev/play/p/L1d6o6l6q0d
|
||||
func Async3[A, B, C any](f func() (A, B, C)) <-chan Tuple3[A, B, C] {
|
||||
ch := make(chan Tuple3[A, B, C], 1)
|
||||
go func() {
|
||||
@@ -72,6 +78,7 @@ func Async3[A, B, C any](f func() (A, B, C)) <-chan Tuple3[A, B, C] {
|
||||
}
|
||||
|
||||
// Async4 has the same behavior as Async, but returns the 4 results as a tuple inside the channel.
|
||||
// Play: https://go.dev/play/p/1X7q6oL0TqF
|
||||
func Async4[A, B, C, D any](f func() (A, B, C, D)) <-chan Tuple4[A, B, C, D] {
|
||||
ch := make(chan Tuple4[A, B, C, D], 1)
|
||||
go func() {
|
||||
@@ -81,6 +88,7 @@ func Async4[A, B, C, D any](f func() (A, B, C, D)) <-chan Tuple4[A, B, C, D] {
|
||||
}
|
||||
|
||||
// Async5 has the same behavior as Async, but returns the 5 results as a tuple inside the channel.
|
||||
// Play: https://go.dev/play/p/2W7q4oL1TqG
|
||||
func Async5[A, B, C, D, E any](f func() (A, B, C, D, E)) <-chan Tuple5[A, B, C, D, E] {
|
||||
ch := make(chan Tuple5[A, B, C, D, E], 1)
|
||||
go func() {
|
||||
@@ -90,6 +98,7 @@ func Async5[A, B, C, D, E any](f func() (A, B, C, D, E)) <-chan Tuple5[A, B, C,
|
||||
}
|
||||
|
||||
// Async6 has the same behavior as Async, but returns the 6 results as a tuple inside the channel.
|
||||
// Play: https://go.dev/play/p/3X8q5pM2UrH
|
||||
func Async6[A, B, C, D, E, F any](f func() (A, B, C, D, E, F)) <-chan Tuple6[A, B, C, D, E, F] {
|
||||
ch := make(chan Tuple6[A, B, C, D, E, F], 1)
|
||||
go func() {
|
||||
@@ -99,6 +108,7 @@ func Async6[A, B, C, D, E, F any](f func() (A, B, C, D, E, F)) <-chan Tuple6[A,
|
||||
}
|
||||
|
||||
// WaitFor runs periodically until a condition is validated.
|
||||
// Play: https://go.dev/play/p/t_wTDmubbK3
|
||||
func WaitFor(condition func(i int) bool, timeout time.Duration, heartbeatDelay time.Duration) (totalIterations int, elapsed time.Duration, conditionFound bool) {
|
||||
conditionWithContext := func(_ context.Context, currentIteration int) bool {
|
||||
return condition(currentIteration)
|
||||
@@ -107,6 +117,7 @@ func WaitFor(condition func(i int) bool, timeout time.Duration, heartbeatDelay t
|
||||
}
|
||||
|
||||
// WaitForWithContext runs periodically until a condition is validated or context is canceled.
|
||||
// Play: https://go.dev/play/p/t_wTDmubbK3
|
||||
func WaitForWithContext(ctx context.Context, condition func(ctx context.Context, currentIteration int) bool, timeout time.Duration, heartbeatDelay time.Duration) (totalIterations int, elapsed time.Duration, conditionFound bool) {
|
||||
start := time.Now()
|
||||
|
||||
|
@@ -61,7 +61,7 @@ func must(err any, messageArgs ...any) {
|
||||
|
||||
// Must is a helper that wraps a call to a function returning a value and an error
|
||||
// and panics if err is error or false.
|
||||
// Play: https://go.dev/play/p/TMoWrRp3DyC
|
||||
// Play: https://go.dev/play/p/fOqtX5HudtN
|
||||
func Must[T any](val T, err any, messageArgs ...any) T {
|
||||
must(err, messageArgs...)
|
||||
return val
|
||||
|
23
find.go
23
find.go
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
// IndexOf returns the index at which the first occurrence of a value is found in an array or return -1
|
||||
// if the value cannot be found.
|
||||
// Play: https://go.dev/play/p/Eo7W0lvKTky
|
||||
func IndexOf[T comparable](collection []T, element T) int {
|
||||
for i := range collection {
|
||||
if collection[i] == element {
|
||||
@@ -22,6 +23,7 @@ func IndexOf[T comparable](collection []T, element T) int {
|
||||
|
||||
// LastIndexOf returns the index at which the last occurrence of a value is found in an array or return -1
|
||||
// if the value cannot be found.
|
||||
// Play: https://go.dev/play/p/Eo7W0lvKTky
|
||||
func LastIndexOf[T comparable](collection []T, element T) int {
|
||||
length := len(collection)
|
||||
|
||||
@@ -35,6 +37,7 @@ func LastIndexOf[T comparable](collection []T, element T) int {
|
||||
}
|
||||
|
||||
// Find search an element in a slice based on a predicate. It returns element and true if element was found.
|
||||
// Play: https://go.dev/play/p/Eo7W0lvKTky
|
||||
func Find[T any](collection []T, predicate func(item T) bool) (T, bool) {
|
||||
for i := range collection {
|
||||
if predicate(collection[i]) {
|
||||
@@ -48,6 +51,7 @@ func Find[T any](collection []T, predicate func(item T) bool) (T, bool) {
|
||||
|
||||
// FindIndexOf searches an element in a slice based on a predicate and returns the index and true.
|
||||
// It returns -1 and false if the element is not found.
|
||||
// Play: https://go.dev/play/p/XWSEM4Ic_t0
|
||||
func FindIndexOf[T any](collection []T, predicate func(item T) bool) (T, int, bool) {
|
||||
for i := range collection {
|
||||
if predicate(collection[i]) {
|
||||
@@ -61,6 +65,7 @@ func FindIndexOf[T any](collection []T, predicate func(item T) bool) (T, int, bo
|
||||
|
||||
// FindLastIndexOf searches last element in a slice based on a predicate and returns the index and true.
|
||||
// It returns -1 and false if the element is not found.
|
||||
// Play: https://go.dev/play/p/dPiMRtJ6cUx
|
||||
func FindLastIndexOf[T any](collection []T, predicate func(item T) bool) (T, int, bool) {
|
||||
length := len(collection)
|
||||
|
||||
@@ -75,6 +80,7 @@ func FindLastIndexOf[T any](collection []T, predicate func(item T) bool) (T, int
|
||||
}
|
||||
|
||||
// FindOrElse search an element in a slice based on a predicate. It returns the element if found or a given fallback value otherwise.
|
||||
// Play: https://go.dev/play/p/Eo7W0lvKTky
|
||||
func FindOrElse[T any](collection []T, fallback T, predicate func(item T) bool) T {
|
||||
for i := range collection {
|
||||
if predicate(collection[i]) {
|
||||
@@ -86,6 +92,7 @@ func FindOrElse[T any](collection []T, fallback T, predicate func(item T) bool)
|
||||
}
|
||||
|
||||
// FindKey returns the key of the first value matching.
|
||||
// Play: https://go.dev/play/p/Bg0w1VDPYXx
|
||||
func FindKey[K comparable, V comparable](object map[K]V, value V) (K, bool) {
|
||||
for k := range object {
|
||||
if object[k] == value {
|
||||
@@ -97,6 +104,7 @@ func FindKey[K comparable, V comparable](object map[K]V, value V) (K, bool) {
|
||||
}
|
||||
|
||||
// FindKeyBy returns the key of the first element predicate returns truthy for.
|
||||
// Play: https://go.dev/play/p/9IbiPElcyo8
|
||||
func FindKeyBy[K comparable, V any](object map[K]V, predicate func(key K, value V) bool) (K, bool) {
|
||||
for k := range object {
|
||||
if predicate(k, object[k]) {
|
||||
@@ -221,6 +229,7 @@ func FindDuplicatesBy[T any, U comparable, Slice ~[]T](collection Slice, iterate
|
||||
|
||||
// Min search the minimum value of a collection.
|
||||
// Returns zero value when the collection is empty.
|
||||
// Play: https://go.dev/play/p/r6e-Z8JozS8
|
||||
func Min[T constraints.Ordered](collection []T) T {
|
||||
var min T
|
||||
|
||||
@@ -365,6 +374,7 @@ func EarliestBy[T any](collection []T, iteratee func(item T) time.Time) T {
|
||||
|
||||
// Max searches the maximum value of a collection.
|
||||
// Returns zero value when the collection is empty.
|
||||
// Play: https://go.dev/play/p/r6e-Z8JozS8
|
||||
func Max[T constraints.Ordered](collection []T) T {
|
||||
var max T
|
||||
|
||||
@@ -508,6 +518,7 @@ func LatestBy[T any](collection []T, iteratee func(item T) time.Time) T {
|
||||
}
|
||||
|
||||
// First returns the first element of a collection and check for availability of the first element.
|
||||
// Play: https://go.dev/play/p/ul45Z0y2EFO
|
||||
func First[T any](collection []T) (T, bool) {
|
||||
length := len(collection)
|
||||
|
||||
@@ -520,12 +531,14 @@ func First[T any](collection []T) (T, bool) {
|
||||
}
|
||||
|
||||
// FirstOrEmpty returns the first element of a collection or zero value if empty.
|
||||
// Play: https://go.dev/play/p/ul45Z0y2EFO
|
||||
func FirstOrEmpty[T any](collection []T) T {
|
||||
i, _ := First(collection)
|
||||
return i
|
||||
}
|
||||
|
||||
// FirstOr returns the first element of a collection or the fallback value if empty.
|
||||
// Play: https://go.dev/play/p/ul45Z0y2EFO
|
||||
func FirstOr[T any](collection []T, fallback T) T {
|
||||
i, ok := First(collection)
|
||||
if !ok {
|
||||
@@ -536,6 +549,7 @@ func FirstOr[T any](collection []T, fallback T) T {
|
||||
}
|
||||
|
||||
// Last returns the last element of a collection or error if empty.
|
||||
// Play: https://go.dev/play/p/ul45Z0y2EFO
|
||||
func Last[T any](collection []T) (T, bool) {
|
||||
length := len(collection)
|
||||
|
||||
@@ -548,12 +562,14 @@ func Last[T any](collection []T) (T, bool) {
|
||||
}
|
||||
|
||||
// LastOrEmpty returns the last element of a collection or zero value if empty.
|
||||
// Play: https://go.dev/play/p/ul45Z0y2EFO
|
||||
func LastOrEmpty[T any](collection []T) T {
|
||||
i, _ := Last(collection)
|
||||
return i
|
||||
}
|
||||
|
||||
// LastOr returns the last element of a collection or the fallback value if empty.
|
||||
// Play: https://go.dev/play/p/ul45Z0y2EFO
|
||||
func LastOr[T any](collection []T, fallback T) T {
|
||||
i, ok := Last(collection)
|
||||
if !ok {
|
||||
@@ -565,6 +581,7 @@ func LastOr[T any](collection []T, fallback T) T {
|
||||
|
||||
// Nth returns the element at index `nth` of collection. If `nth` is negative, the nth element
|
||||
// from the end is returned. An error is returned when nth is out of slice bounds.
|
||||
// Play: https://go.dev/play/p/sHoh88KWt6B
|
||||
func Nth[T any, N constraints.Integer](collection []T, nth N) (T, error) {
|
||||
n := int(nth)
|
||||
l := len(collection)
|
||||
@@ -582,6 +599,7 @@ func Nth[T any, N constraints.Integer](collection []T, nth N) (T, error) {
|
||||
// NthOr returns the element at index `nth` of collection.
|
||||
// If `nth` is negative, it returns the nth element from the end.
|
||||
// If `nth` is out of slice bounds, it returns the fallback value instead of an error.
|
||||
// Play: https://go.dev/play/p/sHoh88KWt6B
|
||||
func NthOr[T any, N constraints.Integer](collection []T, nth N, fallback T) T {
|
||||
value, err := Nth(collection, nth)
|
||||
if err != nil {
|
||||
@@ -593,6 +611,7 @@ func NthOr[T any, N constraints.Integer](collection []T, nth N, fallback T) T {
|
||||
// NthOrEmpty returns the element at index `nth` of collection.
|
||||
// If `nth` is negative, it returns the nth element from the end.
|
||||
// If `nth` is out of slice bounds, it returns the zero value (empty value) for that type.
|
||||
// Play: https://go.dev/play/p/sHoh88KWt6B
|
||||
func NthOrEmpty[T any, N constraints.Integer](collection []T, nth N) T {
|
||||
value, err := Nth(collection, nth)
|
||||
if err != nil {
|
||||
@@ -607,12 +626,14 @@ func NthOrEmpty[T any, N constraints.Integer](collection []T, nth N) T {
|
||||
type randomIntGenerator func(n int) int
|
||||
|
||||
// Sample returns a random item from collection.
|
||||
// Play: https://go.dev/play/p/vCcSJbh5s6l
|
||||
func Sample[T any](collection []T) T {
|
||||
result := SampleBy(collection, rand.IntN)
|
||||
return result
|
||||
}
|
||||
|
||||
// SampleBy returns a random item from collection, using randomIntGenerator as the random index generator.
|
||||
// Play: https://go.dev/play/p/HDmKmMgq0XN
|
||||
func SampleBy[T any](collection []T, randomIntGenerator randomIntGenerator) T {
|
||||
size := len(collection)
|
||||
if size == 0 {
|
||||
@@ -622,12 +643,14 @@ func SampleBy[T any](collection []T, randomIntGenerator randomIntGenerator) T {
|
||||
}
|
||||
|
||||
// Samples returns N random unique items from collection.
|
||||
// Play: https://go.dev/play/p/vCcSJbh5s6l
|
||||
func Samples[T any, Slice ~[]T](collection Slice, count int) Slice {
|
||||
results := SamplesBy(collection, count, rand.IntN)
|
||||
return results
|
||||
}
|
||||
|
||||
// SamplesBy returns N random unique items from collection, using randomIntGenerator as the random index generator.
|
||||
// Play: https://go.dev/play/p/HDmKmMgq0XN
|
||||
func SamplesBy[T any, Slice ~[]T](collection Slice, count int, randomIntGenerator randomIntGenerator) Slice {
|
||||
size := len(collection)
|
||||
|
||||
|
6
func.go
6
func.go
@@ -1,6 +1,7 @@
|
||||
package lo
|
||||
|
||||
// Partial returns new function that, when called, has its first argument set to the provided value.
|
||||
// Play: https://go.dev/play/p/Sy1gAQiQZ3v
|
||||
func Partial[T1, T2, R any](f func(a T1, b T2) R, arg1 T1) func(T2) R {
|
||||
return func(t2 T2) R {
|
||||
return f(arg1, t2)
|
||||
@@ -8,11 +9,13 @@ func Partial[T1, T2, R any](f func(a T1, b T2) R, arg1 T1) func(T2) R {
|
||||
}
|
||||
|
||||
// Partial1 returns new function that, when called, has its first argument set to the provided value.
|
||||
// Play: https://go.dev/play/p/D-ASTXCLBzw
|
||||
func Partial1[T1, T2, R any](f func(T1, T2) R, arg1 T1) func(T2) R {
|
||||
return Partial(f, arg1)
|
||||
}
|
||||
|
||||
// Partial2 returns new function that, when called, has its first argument set to the provided value.
|
||||
// Play: https://go.dev/play/p/-xiPjy4JChJ
|
||||
func Partial2[T1, T2, T3, R any](f func(T1, T2, T3) R, arg1 T1) func(T2, T3) R {
|
||||
return func(t2 T2, t3 T3) R {
|
||||
return f(arg1, t2, t3)
|
||||
@@ -20,6 +23,7 @@ func Partial2[T1, T2, T3, R any](f func(T1, T2, T3) R, arg1 T1) func(T2, T3) R {
|
||||
}
|
||||
|
||||
// Partial3 returns new function that, when called, has its first argument set to the provided value.
|
||||
// Play: https://go.dev/play/p/zWtSutpI26m
|
||||
func Partial3[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) R, arg1 T1) func(T2, T3, T4) R {
|
||||
return func(t2 T2, t3 T3, t4 T4) R {
|
||||
return f(arg1, t2, t3, t4)
|
||||
@@ -27,6 +31,7 @@ func Partial3[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) R, arg1 T1) func(T2,
|
||||
}
|
||||
|
||||
// Partial4 returns new function that, when called, has its first argument set to the provided value.
|
||||
// Play: https://go.dev/play/p/kBrnnMTcJm0
|
||||
func Partial4[T1, T2, T3, T4, T5, R any](f func(T1, T2, T3, T4, T5) R, arg1 T1) func(T2, T3, T4, T5) R {
|
||||
return func(t2 T2, t3 T3, t4 T4, t5 T5) R {
|
||||
return f(arg1, t2, t3, t4, t5)
|
||||
@@ -34,6 +39,7 @@ func Partial4[T1, T2, T3, T4, T5, R any](f func(T1, T2, T3, T4, T5) R, arg1 T1)
|
||||
}
|
||||
|
||||
// Partial5 returns new function that, when called, has its first argument set to the provided value
|
||||
// Play: https://go.dev/play/p/7Is7K2y_VC3
|
||||
func Partial5[T1, T2, T3, T4, T5, T6, R any](f func(T1, T2, T3, T4, T5, T6) R, arg1 T1) func(T2, T3, T4, T5, T6) R {
|
||||
return func(t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) R {
|
||||
return f(arg1, t2, t3, t4, t5, t6)
|
||||
|
16
intersect.go
16
intersect.go
@@ -1,6 +1,7 @@
|
||||
package lo
|
||||
|
||||
// Contains returns true if an element is present in a collection.
|
||||
// Play: https://go.dev/play/p/W1EvyqY6t9j
|
||||
func Contains[T comparable](collection []T, element T) bool {
|
||||
for i := range collection {
|
||||
if collection[i] == element {
|
||||
@@ -12,6 +13,7 @@ func Contains[T comparable](collection []T, element T) bool {
|
||||
}
|
||||
|
||||
// ContainsBy returns true if predicate function return true.
|
||||
// Play: https://go.dev/play/p/W1EvyqY6t9j
|
||||
func ContainsBy[T any](collection []T, predicate func(item T) bool) bool {
|
||||
for i := range collection {
|
||||
if predicate(collection[i]) {
|
||||
@@ -23,6 +25,7 @@ func ContainsBy[T any](collection []T, predicate func(item T) bool) bool {
|
||||
}
|
||||
|
||||
// Every returns true if all elements of a subset are contained into a collection or if the subset is empty.
|
||||
// Play: https://go.dev/play/p/W1EvyqY6t9j
|
||||
func Every[T comparable](collection []T, subset []T) bool {
|
||||
for i := range subset {
|
||||
if !Contains(collection, subset[i]) {
|
||||
@@ -34,6 +37,7 @@ func Every[T comparable](collection []T, subset []T) bool {
|
||||
}
|
||||
|
||||
// EveryBy returns true if the predicate returns true for all elements in the collection or if the collection is empty.
|
||||
// Play: https://go.dev/play/p/dn1-vhHsq9x
|
||||
func EveryBy[T any](collection []T, predicate func(item T) bool) bool {
|
||||
for i := range collection {
|
||||
if !predicate(collection[i]) {
|
||||
@@ -46,6 +50,7 @@ func EveryBy[T any](collection []T, predicate func(item T) bool) bool {
|
||||
|
||||
// Some returns true if at least 1 element of a subset is contained into a collection.
|
||||
// If the subset is empty Some returns false.
|
||||
// Play: https://go.dev/play/p/Lj4ceFkeT9V
|
||||
func Some[T comparable](collection []T, subset []T) bool {
|
||||
for i := range subset {
|
||||
if Contains(collection, subset[i]) {
|
||||
@@ -58,6 +63,7 @@ func Some[T comparable](collection []T, subset []T) bool {
|
||||
|
||||
// SomeBy returns true if the predicate returns true for any of the elements in the collection.
|
||||
// If the collection is empty SomeBy returns false.
|
||||
// Play: https://go.dev/play/p/DXF-TORBudx
|
||||
func SomeBy[T any](collection []T, predicate func(item T) bool) bool {
|
||||
for i := range collection {
|
||||
if predicate(collection[i]) {
|
||||
@@ -69,6 +75,7 @@ func SomeBy[T any](collection []T, predicate func(item T) bool) bool {
|
||||
}
|
||||
|
||||
// None returns true if no element of a subset are contained into a collection or if the subset is empty.
|
||||
// Play: https://go.dev/play/p/fye7JsmxzPV
|
||||
func None[T comparable](collection []T, subset []T) bool {
|
||||
for i := range subset {
|
||||
if Contains(collection, subset[i]) {
|
||||
@@ -80,6 +87,7 @@ func None[T comparable](collection []T, subset []T) bool {
|
||||
}
|
||||
|
||||
// NoneBy returns true if the predicate returns true for none of the elements in the collection or if the collection is empty.
|
||||
// Play: https://go.dev/play/p/O64WZ32H58S
|
||||
func NoneBy[T any](collection []T, predicate func(item T) bool) bool {
|
||||
for i := range collection {
|
||||
if predicate(collection[i]) {
|
||||
@@ -91,6 +99,7 @@ func NoneBy[T any](collection []T, predicate func(item T) bool) bool {
|
||||
}
|
||||
|
||||
// Intersect returns the intersection between two collections.
|
||||
// Play: https://go.dev/play/p/uuElL9X9e58
|
||||
func Intersect[T comparable, Slice ~[]T](list1 Slice, list2 Slice) Slice {
|
||||
result := Slice{}
|
||||
seen := map[T]struct{}{}
|
||||
@@ -111,6 +120,7 @@ func Intersect[T comparable, Slice ~[]T](list1 Slice, list2 Slice) Slice {
|
||||
// Difference returns the difference between two collections.
|
||||
// The first value is the collection of element absent of list2.
|
||||
// The second value is the collection of element absent of list1.
|
||||
// Play: https://go.dev/play/p/pKE-JgzqRpz
|
||||
func Difference[T comparable, Slice ~[]T](list1 Slice, list2 Slice) (Slice, Slice) {
|
||||
left := Slice{}
|
||||
right := Slice{}
|
||||
@@ -143,6 +153,7 @@ func Difference[T comparable, Slice ~[]T](list1 Slice, list2 Slice) (Slice, Slic
|
||||
|
||||
// Union returns all distinct elements from given collections.
|
||||
// result returns will not change the order of elements relatively.
|
||||
// Play: https://go.dev/play/p/DI9RVEB_qMK
|
||||
func Union[T comparable, Slice ~[]T](lists ...Slice) Slice {
|
||||
var capLen int
|
||||
|
||||
@@ -166,6 +177,7 @@ func Union[T comparable, Slice ~[]T](lists ...Slice) Slice {
|
||||
}
|
||||
|
||||
// Without returns slice excluding all given values.
|
||||
// Play: https://go.dev/play/p/5j30Ux8TaD0
|
||||
func Without[T comparable, Slice ~[]T](collection Slice, exclude ...T) Slice {
|
||||
excludeMap := make(map[T]struct{}, len(exclude))
|
||||
for i := range exclude {
|
||||
@@ -183,6 +195,7 @@ func Without[T comparable, Slice ~[]T](collection Slice, exclude ...T) Slice {
|
||||
|
||||
// WithoutBy filters a slice by excluding elements whose extracted keys match any in the exclude list.
|
||||
// It returns a new slice containing only the elements whose keys are not in the exclude list.
|
||||
// Play: https://go.dev/play/p/VgWJOF01NbJ
|
||||
func WithoutBy[T any, K comparable](collection []T, iteratee func(item T) K, exclude ...K) []T {
|
||||
excludeMap := make(map[K]struct{}, len(exclude))
|
||||
for _, e := range exclude {
|
||||
@@ -206,6 +219,7 @@ func WithoutEmpty[T comparable, Slice ~[]T](collection Slice) Slice {
|
||||
}
|
||||
|
||||
// WithoutNth returns slice excluding nth value.
|
||||
// Play: https://go.dev/play/p/5g3F9R2H1xL
|
||||
func WithoutNth[T comparable, Slice ~[]T](collection Slice, nths ...int) Slice {
|
||||
length := len(collection)
|
||||
|
||||
@@ -229,6 +243,7 @@ func WithoutNth[T comparable, Slice ~[]T](collection Slice, nths ...int) Slice {
|
||||
// ElementsMatch returns true if lists contain the same set of elements (including empty set).
|
||||
// If there are duplicate elements, the number of appearances of each of them in both lists should match.
|
||||
// The order of elements is not checked.
|
||||
// Play: https://go.dev/play/p/XWSEM4Ic_t0
|
||||
func ElementsMatch[T comparable, Slice ~[]T](list1 Slice, list2 Slice) bool {
|
||||
return ElementsMatchBy(list1, list2, func(item T) T { return item })
|
||||
}
|
||||
@@ -236,6 +251,7 @@ func ElementsMatch[T comparable, Slice ~[]T](list1 Slice, list2 Slice) bool {
|
||||
// ElementsMatchBy returns true if lists contain the same set of elements' keys (including empty set).
|
||||
// If there are duplicate keys, the number of appearances of each of them in both lists should match.
|
||||
// The order of elements is not checked.
|
||||
// Play: https://go.dev/play/p/XWSEM4Ic_t0
|
||||
func ElementsMatchBy[T any, K comparable](list1 []T, list2 []T, iteratee func(item T) K) bool {
|
||||
if len(list1) != len(list2) {
|
||||
return false
|
||||
|
3
map.go
3
map.go
@@ -175,7 +175,7 @@ func OmitByValues[K comparable, V comparable, Map ~map[K]V](in Map, values []V)
|
||||
}
|
||||
|
||||
// Entries transforms a map into array of key/value pairs.
|
||||
// Play:
|
||||
// Play: https://go.dev/play/p/_t4Xe34-Nl5
|
||||
func Entries[K comparable, V any](in map[K]V) []Entry[K, V] {
|
||||
entries := make([]Entry[K, V], 0, len(in))
|
||||
|
||||
@@ -331,6 +331,7 @@ func MapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(key K, val
|
||||
// The iteratee returns a value and a boolean. If the boolean is true, the value is added to the result slice.
|
||||
// If the boolean is false, the value is not added to the result slice.
|
||||
// The order of the keys in the input map is not specified and the order of the keys in the output slice is not guaranteed.
|
||||
// Play: https://go.dev/play/p/jgsD_Kil9pV
|
||||
func FilterMapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(key K, value V) (R, bool)) []R {
|
||||
result := make([]R, 0, len(in))
|
||||
|
||||
|
2
math.go
2
math.go
@@ -122,6 +122,7 @@ func ProductBy[T any, R constraints.Float | constraints.Integer | constraints.Co
|
||||
}
|
||||
|
||||
// Mean calculates the mean of a collection of numbers.
|
||||
// Play: https://go.dev/play/p/tPURSuteUsP
|
||||
func Mean[T constraints.Float | constraints.Integer](collection []T) T {
|
||||
length := T(len(collection))
|
||||
if length == 0 {
|
||||
@@ -132,6 +133,7 @@ func Mean[T constraints.Float | constraints.Integer](collection []T) T {
|
||||
}
|
||||
|
||||
// MeanBy calculates the mean of a collection of numbers using the given return value from the iteration function.
|
||||
// Play: https://go.dev/play/p/j7TsVwBOZ7P
|
||||
func MeanBy[T any, R constraints.Float | constraints.Integer](collection []T, iteratee func(item T) R) R {
|
||||
length := R(len(collection))
|
||||
if length == 0 {
|
||||
|
@@ -7,6 +7,7 @@ import "github.com/samber/lo/internal/rand"
|
||||
// and should return true for elements that should be kept and false for elements that should be removed.
|
||||
// The function returns the modified slice, which may be shorter than the original if some elements were removed.
|
||||
// Note that the order of elements in the original slice is preserved in the output.
|
||||
// Play: https://go.dev/play/p/0jY3Z0B7O_5
|
||||
func Filter[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice {
|
||||
j := 0
|
||||
for _, item := range collection {
|
||||
@@ -36,6 +37,7 @@ func FilterI[T any, Slice ~[]T](collection Slice, predicate func(item T, index i
|
||||
|
||||
// Map is a generic function that modifies the input slice in-place to contain the result of applying the provided
|
||||
// function to each element of the slice. The function returns the modified slice, which has the same length as the original.
|
||||
// Play: https://go.dev/play/p/0jY3Z0B7O_5
|
||||
func Map[T any, Slice ~[]T](collection Slice, fn func(item T) T) {
|
||||
for i := range collection {
|
||||
collection[i] = fn(collection[i])
|
||||
|
@@ -4,6 +4,7 @@ import "sync"
|
||||
|
||||
// Map manipulates a slice and transforms it to a slice of another type.
|
||||
// `iteratee` is call in parallel. Result keep the same order.
|
||||
// Play: https://go.dev/play/p/sCJaB3quRMC
|
||||
func Map[T any, R any](collection []T, iteratee func(item T, index int) R) []R {
|
||||
result := make([]R, len(collection))
|
||||
|
||||
@@ -27,6 +28,7 @@ func Map[T any, R any](collection []T, iteratee func(item T, index int) R) []R {
|
||||
|
||||
// ForEach iterates over elements of collection and invokes iteratee for each element.
|
||||
// `iteratee` is call in parallel.
|
||||
// Play: https://go.dev/play/p/sCJaB3quRMC
|
||||
func ForEach[T any](collection []T, iteratee func(item T, index int)) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(collection))
|
||||
|
9
retry.go
9
retry.go
@@ -194,6 +194,7 @@ func AttemptWithDelay(maxIteration int, delay time.Duration, f func(index int, d
|
||||
// immediately if the second return value is false. When the first
|
||||
// argument is less than `1`, the function runs until a successful response is
|
||||
// returned.
|
||||
// Play: https://go.dev/play/p/1VS7HxlYMOG
|
||||
func AttemptWhile(maxIteration int, f func(int) (error, bool)) (int, error) {
|
||||
var err error
|
||||
var shouldContinueInvoke bool
|
||||
@@ -218,6 +219,7 @@ func AttemptWhile(maxIteration int, f func(int) (error, bool)) (int, error) {
|
||||
// It will terminate the invoke immediately if the second return value is false.
|
||||
// When the first argument is less than `1`, the function runs until a successful
|
||||
// response is returned.
|
||||
// Play: https://go.dev/play/p/mhufUjJfLEF
|
||||
func AttemptWhileWithDelay(maxIteration int, delay time.Duration, f func(int, time.Duration) (error, bool)) (int, time.Duration, error) {
|
||||
var err error
|
||||
var shouldContinueInvoke bool
|
||||
@@ -247,6 +249,7 @@ type transactionStep[T any] struct {
|
||||
}
|
||||
|
||||
// NewTransaction instantiate a new transaction.
|
||||
// Play: https://go.dev/play/p/Qxrd7MGQGh1
|
||||
func NewTransaction[T any]() *Transaction[T] {
|
||||
return &Transaction[T]{
|
||||
steps: []transactionStep[T]{},
|
||||
@@ -259,6 +262,7 @@ type Transaction[T any] struct {
|
||||
}
|
||||
|
||||
// Then adds a step to the chain of callbacks. It returns the same Transaction.
|
||||
// Play: https://go.dev/play/p/Qxrd7MGQGh1 https://go.dev/play/p/xrHb2_kMvTY
|
||||
func (t *Transaction[T]) Then(exec func(T) (T, error), onRollback func(T) T) *Transaction[T] {
|
||||
t.steps = append(t.steps, transactionStep[T]{
|
||||
exec: exec,
|
||||
@@ -269,6 +273,7 @@ func (t *Transaction[T]) Then(exec func(T) (T, error), onRollback func(T) T) *Tr
|
||||
}
|
||||
|
||||
// Process runs the Transaction steps and rollbacks in case of errors.
|
||||
// Play: https://go.dev/play/p/Qxrd7MGQGh1 https://go.dev/play/p/xrHb2_kMvTY
|
||||
func (t *Transaction[T]) Process(state T) (T, error) {
|
||||
var i int
|
||||
var err error
|
||||
@@ -341,11 +346,13 @@ func (th *throttleBy[T]) reset() {
|
||||
|
||||
// NewThrottle creates a throttled instance that invokes given functions only once in every interval.
|
||||
// This returns 2 functions, First one is throttled function and Second one is a function to reset interval
|
||||
// Play: https://go.dev/play/p/qQn3fm8Z7jS
|
||||
func NewThrottle(interval time.Duration, f ...func()) (throttle func(), reset func()) {
|
||||
return NewThrottleWithCount(interval, 1, f...)
|
||||
}
|
||||
|
||||
// NewThrottleWithCount is NewThrottle with count limit, throttled function will be invoked count times in every interval.
|
||||
// Play: https://go.dev/play/p/w5nc0MgWtjC
|
||||
func NewThrottleWithCount(interval time.Duration, count int, f ...func()) (throttle func(), reset func()) {
|
||||
callbacks := Map(f, func(item func(), _ int) func(struct{}) {
|
||||
return func(struct{}) {
|
||||
@@ -361,11 +368,13 @@ func NewThrottleWithCount(interval time.Duration, count int, f ...func()) (throt
|
||||
|
||||
// NewThrottleBy creates a throttled instance that invokes given functions only once in every interval.
|
||||
// This returns 2 functions, First one is throttled function and Second one is a function to reset interval
|
||||
// Play: https://go.dev/play/p/0Wv6oX7dHdC
|
||||
func NewThrottleBy[T comparable](interval time.Duration, f ...func(key T)) (throttle func(key T), reset func()) {
|
||||
return NewThrottleByWithCount[T](interval, 1, f...)
|
||||
}
|
||||
|
||||
// NewThrottleByWithCount is NewThrottleBy with count limit, throttled function will be invoked count times in every interval.
|
||||
// Play: https://go.dev/play/p/vQk3ECH7_EW
|
||||
func NewThrottleByWithCount[T comparable](interval time.Duration, count int, f ...func(key T)) (throttle func(key T), reset func()) {
|
||||
if count <= 0 {
|
||||
count = 1
|
||||
|
19
slice.go
19
slice.go
@@ -34,6 +34,7 @@ func Map[T any, R any](collection []T, iteratee func(item T, index int) R) []R {
|
||||
}
|
||||
|
||||
// UniqMap manipulates a slice and transforms it to a slice of another type with unique values.
|
||||
// Play: https://go.dev/play/p/fygzLBhvUdB
|
||||
func UniqMap[T any, R comparable](collection []T, iteratee func(item T, index int) R) []R {
|
||||
result := make([]R, 0, len(collection))
|
||||
seen := make(map[R]struct{}, len(collection))
|
||||
@@ -53,7 +54,7 @@ func UniqMap[T any, R comparable](collection []T, iteratee func(item T, index in
|
||||
// - the result of the mapping operation and
|
||||
// - whether the result element should be included or not.
|
||||
//
|
||||
// Play: https://go.dev/play/p/-AuYXfy7opz
|
||||
// Play: https://go.dev/play/p/CgHYNUpOd1I
|
||||
func FilterMap[T any, R any](collection []T, callback func(item T, index int) (R, bool)) []R {
|
||||
result := make([]R, 0, len(collection))
|
||||
|
||||
@@ -69,7 +70,7 @@ func FilterMap[T any, R any](collection []T, callback func(item T, index int) (R
|
||||
// FlatMap manipulates a slice and transforms and flattens it to a slice of another type.
|
||||
// The transform function can either return a slice or a `nil`, and in the `nil` case
|
||||
// no value is added to the final slice.
|
||||
// Play: https://go.dev/play/p/YSoYmQTA8-U
|
||||
// Play: https://go.dev/play/p/pFCF5WVB225
|
||||
func FlatMap[T any, R any](collection []T, iteratee func(item T, index int) []R) []R {
|
||||
result := make([]R, 0, len(collection))
|
||||
|
||||
@@ -82,7 +83,7 @@ func FlatMap[T any, R any](collection []T, iteratee func(item T, index int) []R)
|
||||
|
||||
// Reduce reduces collection to a value which is the accumulated result of running each element in collection
|
||||
// through accumulator, where each successive invocation is supplied the return value of the previous.
|
||||
// Play: https://go.dev/play/p/R4UHXZNaaUG
|
||||
// Play: https://go.dev/play/p/CgHYNUpOd1I
|
||||
func Reduce[T any, R any](collection []T, accumulator func(agg R, item T, index int) R, initial R) R {
|
||||
for i := range collection {
|
||||
initial = accumulator(initial, collection[i], i)
|
||||
@@ -189,6 +190,7 @@ func GroupBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(it
|
||||
}
|
||||
|
||||
// GroupByMap returns an object composed of keys generated from the results of running each element of collection through iteratee.
|
||||
// Play: https://go.dev/play/p/iMeruQ3_W80
|
||||
func GroupByMap[T any, K comparable, V any](collection []T, iteratee func(item T) (K, V)) map[K][]V {
|
||||
result := map[K][]V{}
|
||||
|
||||
@@ -203,7 +205,7 @@ func GroupByMap[T any, K comparable, V any](collection []T, iteratee func(item T
|
||||
|
||||
// Chunk returns an array of elements split into groups the length of size. If array can't be split evenly,
|
||||
// the final chunk will be the remaining elements.
|
||||
// Play: https://go.dev/play/p/EeKl0AuTehH
|
||||
// Play: https://go.dev/play/p/kEMkFbdu85g
|
||||
func Chunk[T any, Slice ~[]T](collection Slice, size int) []Slice {
|
||||
if size <= 0 {
|
||||
panic("Second parameter must be greater than 0")
|
||||
@@ -368,7 +370,7 @@ func RepeatBy[T any](count int, predicate func(index int) T) []T {
|
||||
}
|
||||
|
||||
// KeyBy transforms a slice or an array of structs to a map based on a pivot callback.
|
||||
// Play: https://go.dev/play/p/mdaClUAT-zZ
|
||||
// Play: https://go.dev/play/p/ccUiUL_Lnel
|
||||
func KeyBy[K comparable, V any](collection []V, iteratee func(item V) K) map[K]V {
|
||||
result := make(map[K]V, len(collection))
|
||||
|
||||
@@ -408,6 +410,7 @@ func SliceToMap[T any, K comparable, V any](collection []T, transform func(item
|
||||
// If any of two pairs would have the same key the last one gets added to the map.
|
||||
// The order of keys in returned map is not specified and is not guaranteed to be the same from the original array.
|
||||
// The third return value of the transform function is a boolean that indicates whether the key-value pair should be included in the map.
|
||||
// Play: https://go.dev/play/p/2z0rDz2ZSGU
|
||||
func FilterSliceToMap[T any, K comparable, V any](collection []T, transform func(item T) (K, V, bool)) map[K]V {
|
||||
result := make(map[K]V, len(collection))
|
||||
|
||||
@@ -422,6 +425,7 @@ func FilterSliceToMap[T any, K comparable, V any](collection []T, transform func
|
||||
}
|
||||
|
||||
// Keyify returns a map with each unique element of the slice as a key.
|
||||
// Play: https://go.dev/play/p/RYhhM_csqIG
|
||||
func Keyify[T comparable, Slice ~[]T](collection Slice) map[T]struct{} {
|
||||
result := make(map[T]struct{}, len(collection))
|
||||
|
||||
@@ -516,7 +520,7 @@ func DropByIndex[T any](collection []T, indexes ...int) []T {
|
||||
}
|
||||
|
||||
// Reject is the opposite of Filter, this method returns the elements of collection that predicate does not return truthy for.
|
||||
// Play: https://go.dev/play/p/YkLMODy1WEL
|
||||
// Play: https://go.dev/play/p/pFCF5WVB225
|
||||
func Reject[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice {
|
||||
result := Slice{}
|
||||
|
||||
@@ -533,6 +537,8 @@ func Reject[T any, Slice ~[]T](collection Slice, predicate func(item T, index in
|
||||
// The callback function should return two values:
|
||||
// - the result of the mapping operation and
|
||||
// - whether the result element should be included or not.
|
||||
//
|
||||
// Play: https://go.dev/play/p/W9Ug9r0QFkL
|
||||
func RejectMap[T any, R any](collection []T, callback func(item T, index int) (R, bool)) []R {
|
||||
result := []R{}
|
||||
|
||||
@@ -547,6 +553,7 @@ func RejectMap[T any, R any](collection []T, callback func(item T, index int) (R
|
||||
|
||||
// FilterReject mixes Filter and Reject, this method returns two slices, one for the elements of collection that
|
||||
// predicate returns truthy for and one for the elements that predicate does not return truthy for.
|
||||
// Play: https://go.dev/play/p/lHSEGSznJjB
|
||||
func FilterReject[T any, Slice ~[]T](collection Slice, predicate func(T, int) bool) (kept Slice, rejected Slice) {
|
||||
kept = make(Slice, 0, len(collection))
|
||||
rejected = make(Slice, 0, len(collection))
|
||||
|
@@ -151,6 +151,7 @@ func RuneLength(str string) int {
|
||||
}
|
||||
|
||||
// PascalCase converts string to pascal case.
|
||||
// Play: https://go.dev/play/p/Dy_V_6DUYhe
|
||||
func PascalCase(str string) string {
|
||||
items := Words(str)
|
||||
for i := range items {
|
||||
@@ -160,6 +161,7 @@ func PascalCase(str string) string {
|
||||
}
|
||||
|
||||
// CamelCase converts string to camel case.
|
||||
// Play: https://go.dev/play/p/Go6aKwUiq59
|
||||
func CamelCase(str string) string {
|
||||
items := Words(str)
|
||||
for i, item := range items {
|
||||
@@ -173,6 +175,7 @@ func CamelCase(str string) string {
|
||||
}
|
||||
|
||||
// KebabCase converts string to kebab case.
|
||||
// Play: https://go.dev/play/p/96gT_WZnTVP
|
||||
func KebabCase(str string) string {
|
||||
items := Words(str)
|
||||
for i := range items {
|
||||
@@ -182,6 +185,7 @@ func KebabCase(str string) string {
|
||||
}
|
||||
|
||||
// SnakeCase converts string to snake case.
|
||||
// Play: https://go.dev/play/p/ziB0V89IeVH
|
||||
func SnakeCase(str string) string {
|
||||
items := Words(str)
|
||||
for i := range items {
|
||||
@@ -191,6 +195,7 @@ func SnakeCase(str string) string {
|
||||
}
|
||||
|
||||
// Words splits string into an array of its words.
|
||||
// Play: https://go.dev/play/p/-f3VIQqiaVw
|
||||
func Words(str string) []string {
|
||||
str = splitWordReg.ReplaceAllString(str, `$1$3$5$7 $2$4$6$8$9`)
|
||||
// example: Int8Value => Int 8Value => Int 8 Value
|
||||
@@ -207,6 +212,7 @@ func Words(str string) []string {
|
||||
}
|
||||
|
||||
// Capitalize converts the first character of string to upper case and the remaining to lower case.
|
||||
// Play: https://go.dev/play/p/uLTZZQXqnsa
|
||||
func Capitalize(str string) string {
|
||||
return cases.Title(language.English).String(str)
|
||||
}
|
||||
@@ -214,6 +220,7 @@ func Capitalize(str string) string {
|
||||
// Ellipsis trims and truncates a string to a specified length **in bytes** and appends an ellipsis
|
||||
// if truncated. If the string contains non-ASCII characters (which may occupy multiple bytes in UTF-8),
|
||||
// truncating by byte length may split a character in the middle, potentially resulting in garbled output.
|
||||
// Play: https://go.dev/play/p/qE93rgqe1TW
|
||||
func Ellipsis(str string, length int) string {
|
||||
str = strings.TrimSpace(str)
|
||||
|
||||
|
12
time.go
12
time.go
@@ -3,11 +3,13 @@ package lo
|
||||
import "time"
|
||||
|
||||
// Duration returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/HQfbBbAXaFP
|
||||
func Duration(cb func()) time.Duration {
|
||||
return Duration0(cb)
|
||||
}
|
||||
|
||||
// Duration0 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/HQfbBbAXaFP
|
||||
func Duration0(cb func()) time.Duration {
|
||||
start := time.Now()
|
||||
cb()
|
||||
@@ -15,6 +17,7 @@ func Duration0(cb func()) time.Duration {
|
||||
}
|
||||
|
||||
// Duration1 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/HQfbBbAXaFP
|
||||
func Duration1[A any](cb func() A) (A, time.Duration) {
|
||||
start := time.Now()
|
||||
a := cb()
|
||||
@@ -22,6 +25,7 @@ func Duration1[A any](cb func() A) (A, time.Duration) {
|
||||
}
|
||||
|
||||
// Duration2 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/HQfbBbAXaFP
|
||||
func Duration2[A, B any](cb func() (A, B)) (A, B, time.Duration) {
|
||||
start := time.Now()
|
||||
a, b := cb()
|
||||
@@ -29,6 +33,7 @@ func Duration2[A, B any](cb func() (A, B)) (A, B, time.Duration) {
|
||||
}
|
||||
|
||||
// Duration3 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/xr863iwkAxQ
|
||||
func Duration3[A, B, C any](cb func() (A, B, C)) (A, B, C, time.Duration) {
|
||||
start := time.Now()
|
||||
a, b, c := cb()
|
||||
@@ -36,6 +41,7 @@ func Duration3[A, B, C any](cb func() (A, B, C)) (A, B, C, time.Duration) {
|
||||
}
|
||||
|
||||
// Duration4 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/xr863iwkAxQ
|
||||
func Duration4[A, B, C, D any](cb func() (A, B, C, D)) (A, B, C, D, time.Duration) {
|
||||
start := time.Now()
|
||||
a, b, c, d := cb()
|
||||
@@ -43,6 +49,7 @@ func Duration4[A, B, C, D any](cb func() (A, B, C, D)) (A, B, C, D, time.Duratio
|
||||
}
|
||||
|
||||
// Duration5 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/xr863iwkAxQ
|
||||
func Duration5[A, B, C, D, E any](cb func() (A, B, C, D, E)) (A, B, C, D, E, time.Duration) {
|
||||
start := time.Now()
|
||||
a, b, c, d, e := cb()
|
||||
@@ -50,6 +57,7 @@ func Duration5[A, B, C, D, E any](cb func() (A, B, C, D, E)) (A, B, C, D, E, tim
|
||||
}
|
||||
|
||||
// Duration6 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/mR4bTQKO-Tf
|
||||
func Duration6[A, B, C, D, E, F any](cb func() (A, B, C, D, E, F)) (A, B, C, D, E, F, time.Duration) {
|
||||
start := time.Now()
|
||||
a, b, c, d, e, f := cb()
|
||||
@@ -57,6 +65,7 @@ func Duration6[A, B, C, D, E, F any](cb func() (A, B, C, D, E, F)) (A, B, C, D,
|
||||
}
|
||||
|
||||
// Duration7 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/jgIAcBWWInS
|
||||
func Duration7[A, B, C, D, E, F, G any](cb func() (A, B, C, D, E, F, G)) (A, B, C, D, E, F, G, time.Duration) {
|
||||
start := time.Now()
|
||||
a, b, c, d, e, f, g := cb()
|
||||
@@ -64,6 +73,7 @@ func Duration7[A, B, C, D, E, F, G any](cb func() (A, B, C, D, E, F, G)) (A, B,
|
||||
}
|
||||
|
||||
// Duration8 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/T8kxpG1c5Na
|
||||
func Duration8[A, B, C, D, E, F, G, H any](cb func() (A, B, C, D, E, F, G, H)) (A, B, C, D, E, F, G, H, time.Duration) {
|
||||
start := time.Now()
|
||||
a, b, c, d, e, f, g, h := cb()
|
||||
@@ -71,6 +81,7 @@ func Duration8[A, B, C, D, E, F, G, H any](cb func() (A, B, C, D, E, F, G, H)) (
|
||||
}
|
||||
|
||||
// Duration9 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/bg9ix2VrZ0j
|
||||
func Duration9[A, B, C, D, E, F, G, H, I any](cb func() (A, B, C, D, E, F, G, H, I)) (A, B, C, D, E, F, G, H, I, time.Duration) {
|
||||
start := time.Now()
|
||||
a, b, c, d, e, f, g, h, i := cb()
|
||||
@@ -78,6 +89,7 @@ func Duration9[A, B, C, D, E, F, G, H, I any](cb func() (A, B, C, D, E, F, G, H,
|
||||
}
|
||||
|
||||
// Duration10 returns the time taken to execute a function.
|
||||
// Play: https://go.dev/play/p/Y3n7oJXqJbk
|
||||
func Duration10[A, B, C, D, E, F, G, H, I, J any](cb func() (A, B, C, D, E, F, G, H, I, J)) (A, B, C, D, E, F, G, H, I, J, time.Duration) {
|
||||
start := time.Now()
|
||||
a, b, c, d, e, f, g, h, i, j := cb()
|
||||
|
32
tuples.go
32
tuples.go
@@ -331,6 +331,7 @@ func Zip9[A, B, C, D, E, F, G, H, I any](a []A, b []B, c []C, d []D, e []E, f []
|
||||
// ZipBy2 creates a slice of transformed elements, the first of which contains the first elements
|
||||
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
|
||||
// When collections have different size, the Tuple attributes are filled with zero value.
|
||||
// Play: https://go.dev/play/p/wlHur6yO8rR
|
||||
func ZipBy2[A any, B any, Out any](a []A, b []B, iteratee func(a A, b B) Out) []Out {
|
||||
size := Max([]int{len(a), len(b)})
|
||||
|
||||
@@ -349,6 +350,7 @@ func ZipBy2[A any, B any, Out any](a []A, b []B, iteratee func(a A, b B) Out) []
|
||||
// ZipBy3 creates a slice of transformed elements, the first of which contains the first elements
|
||||
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
|
||||
// When collections have different size, the Tuple attributes are filled with zero value.
|
||||
// Play: https://go.dev/play/p/j9maveOnSQX
|
||||
func ZipBy3[A any, B any, C any, Out any](a []A, b []B, c []C, iteratee func(a A, b B, c C) Out) []Out {
|
||||
size := Max([]int{len(a), len(b), len(c)})
|
||||
|
||||
@@ -368,6 +370,7 @@ func ZipBy3[A any, B any, C any, Out any](a []A, b []B, c []C, iteratee func(a A
|
||||
// ZipBy4 creates a slice of transformed elements, the first of which contains the first elements
|
||||
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
|
||||
// When collections have different size, the Tuple attributes are filled with zero value.
|
||||
// Play: https://go.dev/play/p/Y1eF2Ke0Ayz
|
||||
func ZipBy4[A any, B any, C any, D any, Out any](a []A, b []B, c []C, d []D, iteratee func(a A, b B, c C, d D) Out) []Out {
|
||||
size := Max([]int{len(a), len(b), len(c), len(d)})
|
||||
|
||||
@@ -388,6 +391,7 @@ func ZipBy4[A any, B any, C any, D any, Out any](a []A, b []B, c []C, d []D, ite
|
||||
// ZipBy5 creates a slice of transformed elements, the first of which contains the first elements
|
||||
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
|
||||
// When collections have different size, the Tuple attributes are filled with zero value.
|
||||
// Play: https://go.dev/play/p/SLynyalh5Oa
|
||||
func ZipBy5[A any, B any, C any, D any, E any, Out any](a []A, b []B, c []C, d []D, e []E, iteratee func(a A, b B, c C, d D, e E) Out) []Out {
|
||||
size := Max([]int{len(a), len(b), len(c), len(d), len(e)})
|
||||
|
||||
@@ -409,6 +413,7 @@ func ZipBy5[A any, B any, C any, D any, E any, Out any](a []A, b []B, c []C, d [
|
||||
// ZipBy6 creates a slice of transformed elements, the first of which contains the first elements
|
||||
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
|
||||
// When collections have different size, the Tuple attributes are filled with zero value.
|
||||
// Play: https://go.dev/play/p/IK6KVgw9e-S
|
||||
func ZipBy6[A any, B any, C any, D any, E any, F any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, iteratee func(a A, b B, c C, d D, e E, f F) Out) []Out {
|
||||
size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f)})
|
||||
|
||||
@@ -431,6 +436,7 @@ func ZipBy6[A any, B any, C any, D any, E any, F any, Out any](a []A, b []B, c [
|
||||
// ZipBy7 creates a slice of transformed elements, the first of which contains the first elements
|
||||
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
|
||||
// When collections have different size, the Tuple attributes are filled with zero value.
|
||||
// Play: https://go.dev/play/p/4uW6a2vXh8w
|
||||
func ZipBy7[A any, B any, C any, D any, E any, F any, G any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, iteratee func(a A, b B, c C, d D, e E, f F, g G) Out) []Out {
|
||||
size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g)})
|
||||
|
||||
@@ -454,6 +460,7 @@ func ZipBy7[A any, B any, C any, D any, E any, F any, G any, Out any](a []A, b [
|
||||
// ZipBy8 creates a slice of transformed elements, the first of which contains the first elements
|
||||
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
|
||||
// When collections have different size, the Tuple attributes are filled with zero value.
|
||||
// Play: https://go.dev/play/p/tk8xW7XzY4v
|
||||
func ZipBy8[A any, B any, C any, D any, E any, F any, G any, H any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H) Out) []Out {
|
||||
size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h)})
|
||||
|
||||
@@ -478,6 +485,7 @@ func ZipBy8[A any, B any, C any, D any, E any, F any, G any, H any, Out any](a [
|
||||
// ZipBy9 creates a slice of transformed elements, the first of which contains the first elements
|
||||
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
|
||||
// When collections have different size, the Tuple attributes are filled with zero value.
|
||||
// Play: https://go.dev/play/p/VGqjDmQ9YqX
|
||||
func ZipBy9[A any, B any, C any, D any, E any, F any, G any, H any, I any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, i []I, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H, i I) Out) []Out {
|
||||
size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h), len(i)})
|
||||
|
||||
@@ -686,6 +694,7 @@ func Unzip9[A, B, C, D, E, F, G, H, I any](tuples []Tuple9[A, B, C, D, E, F, G,
|
||||
|
||||
// UnzipBy2 iterates over a collection and creates an array regrouping the elements
|
||||
// to their pre-zip configuration.
|
||||
// Play: https://go.dev/play/p/tN8yqaRZz0r
|
||||
func UnzipBy2[In any, A any, B any](items []In, iteratee func(In) (a A, b B)) ([]A, []B) {
|
||||
size := len(items)
|
||||
r1 := make([]A, 0, size)
|
||||
@@ -702,6 +711,7 @@ func UnzipBy2[In any, A any, B any](items []In, iteratee func(In) (a A, b B)) ([
|
||||
|
||||
// UnzipBy3 iterates over a collection and creates an array regrouping the elements
|
||||
// to their pre-zip configuration.
|
||||
// Play: https://go.dev/play/p/36ITO2DlQq1
|
||||
func UnzipBy3[In any, A any, B any, C any](items []In, iteratee func(In) (a A, b B, c C)) ([]A, []B, []C) {
|
||||
size := len(items)
|
||||
r1 := make([]A, 0, size)
|
||||
@@ -720,6 +730,7 @@ func UnzipBy3[In any, A any, B any, C any](items []In, iteratee func(In) (a A, b
|
||||
|
||||
// UnzipBy4 iterates over a collection and creates an array regrouping the elements
|
||||
// to their pre-zip configuration.
|
||||
// Play: https://go.dev/play/p/zJ6qY1dD1rL
|
||||
func UnzipBy4[In any, A any, B any, C any, D any](items []In, iteratee func(In) (a A, b B, c C, d D)) ([]A, []B, []C, []D) {
|
||||
size := len(items)
|
||||
r1 := make([]A, 0, size)
|
||||
@@ -740,6 +751,7 @@ func UnzipBy4[In any, A any, B any, C any, D any](items []In, iteratee func(In)
|
||||
|
||||
// UnzipBy5 iterates over a collection and creates an array regrouping the elements
|
||||
// to their pre-zip configuration.
|
||||
// Play: https://go.dev/play/p/3f7jKkV9xZt
|
||||
func UnzipBy5[In any, A any, B any, C any, D any, E any](items []In, iteratee func(In) (a A, b B, c C, d D, e E)) ([]A, []B, []C, []D, []E) {
|
||||
size := len(items)
|
||||
r1 := make([]A, 0, size)
|
||||
@@ -762,6 +774,7 @@ func UnzipBy5[In any, A any, B any, C any, D any, E any](items []In, iteratee fu
|
||||
|
||||
// UnzipBy6 iterates over a collection and creates an array regrouping the elements
|
||||
// to their pre-zip configuration.
|
||||
// Play: https://go.dev/play/p/8Y1b7tKu2pL
|
||||
func UnzipBy6[In any, A any, B any, C any, D any, E any, F any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F)) ([]A, []B, []C, []D, []E, []F) {
|
||||
size := len(items)
|
||||
r1 := make([]A, 0, size)
|
||||
@@ -786,6 +799,7 @@ func UnzipBy6[In any, A any, B any, C any, D any, E any, F any](items []In, iter
|
||||
|
||||
// UnzipBy7 iterates over a collection and creates an array regrouping the elements
|
||||
// to their pre-zip configuration.
|
||||
// Play: https://go.dev/play/p/7j1kLmVn3pM
|
||||
func UnzipBy7[In any, A any, B any, C any, D any, E any, F any, G any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G)) ([]A, []B, []C, []D, []E, []F, []G) {
|
||||
size := len(items)
|
||||
r1 := make([]A, 0, size)
|
||||
@@ -812,6 +826,7 @@ func UnzipBy7[In any, A any, B any, C any, D any, E any, F any, G any](items []I
|
||||
|
||||
// UnzipBy8 iterates over a collection and creates an array regrouping the elements
|
||||
// to their pre-zip configuration.
|
||||
// Play: https://go.dev/play/p/1n2k3L4m5N6
|
||||
func UnzipBy8[In any, A any, B any, C any, D any, E any, F any, G any, H any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G, h H)) ([]A, []B, []C, []D, []E, []F, []G, []H) {
|
||||
size := len(items)
|
||||
r1 := make([]A, 0, size)
|
||||
@@ -840,6 +855,7 @@ func UnzipBy8[In any, A any, B any, C any, D any, E any, F any, G any, H any](it
|
||||
|
||||
// UnzipBy9 iterates over a collection and creates an array regrouping the elements
|
||||
// to their pre-zip configuration.
|
||||
// Play: https://go.dev/play/p/7o8p9q0r1s2
|
||||
func UnzipBy9[In any, A any, B any, C any, D any, E any, F any, G any, H any, I any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G, h H, i I)) ([]A, []B, []C, []D, []E, []F, []G, []H, []I) {
|
||||
size := len(items)
|
||||
r1 := make([]A, 0, size)
|
||||
@@ -871,6 +887,7 @@ func UnzipBy9[In any, A any, B any, C any, D any, E any, F any, G any, H any, I
|
||||
// CrossJoin2 combines every items from one list with every items from others.
|
||||
// It is the cartesian product of lists received as arguments.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/3VFppyL9FDU
|
||||
func CrossJoin2[A, B any](listA []A, listB []B) []Tuple2[A, B] {
|
||||
return CrossJoinBy2(listA, listB, T2[A, B])
|
||||
}
|
||||
@@ -878,6 +895,7 @@ func CrossJoin2[A, B any](listA []A, listB []B) []Tuple2[A, B] {
|
||||
// CrossJoin3 combines every items from one list with every items from others.
|
||||
// It is the cartesian product of lists received as arguments.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/2WGeHyJj4fK
|
||||
func CrossJoin3[A, B, C any](listA []A, listB []B, listC []C) []Tuple3[A, B, C] {
|
||||
return CrossJoinBy3(listA, listB, listC, T3[A, B, C])
|
||||
}
|
||||
@@ -885,6 +903,7 @@ func CrossJoin3[A, B, C any](listA []A, listB []B, listC []C) []Tuple3[A, B, C]
|
||||
// CrossJoin4 combines every items from one list with every items from others.
|
||||
// It is the cartesian product of lists received as arguments.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/6XhKjLmMnNp
|
||||
func CrossJoin4[A, B, C, D any](listA []A, listB []B, listC []C, listD []D) []Tuple4[A, B, C, D] {
|
||||
return CrossJoinBy4(listA, listB, listC, listD, T4[A, B, C, D])
|
||||
}
|
||||
@@ -892,6 +911,7 @@ func CrossJoin4[A, B, C, D any](listA []A, listB []B, listC []C, listD []D) []Tu
|
||||
// CrossJoin5 combines every items from one list with every items from others.
|
||||
// It is the cartesian product of lists received as arguments.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/7oPqRsTuVwX
|
||||
func CrossJoin5[A, B, C, D, E any](listA []A, listB []B, listC []C, listD []D, listE []E) []Tuple5[A, B, C, D, E] {
|
||||
return CrossJoinBy5(listA, listB, listC, listD, listE, T5[A, B, C, D, E])
|
||||
}
|
||||
@@ -899,6 +919,7 @@ func CrossJoin5[A, B, C, D, E any](listA []A, listB []B, listC []C, listD []D, l
|
||||
// CrossJoin6 combines every items from one list with every items from others.
|
||||
// It is the cartesian product of lists received as arguments.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/8yZ1aB2cD3e
|
||||
func CrossJoin6[A, B, C, D, E, F any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F) []Tuple6[A, B, C, D, E, F] {
|
||||
return CrossJoinBy6(listA, listB, listC, listD, listE, listF, T6[A, B, C, D, E, F])
|
||||
}
|
||||
@@ -906,6 +927,7 @@ func CrossJoin6[A, B, C, D, E, F any](listA []A, listB []B, listC []C, listD []D
|
||||
// CrossJoin7 combines every items from one list with every items from others.
|
||||
// It is the cartesian product of lists received as arguments.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/9f4g5h6i7j8
|
||||
func CrossJoin7[A, B, C, D, E, F, G any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G) []Tuple7[A, B, C, D, E, F, G] {
|
||||
return CrossJoinBy7(listA, listB, listC, listD, listE, listF, listG, T7[A, B, C, D, E, F, G])
|
||||
}
|
||||
@@ -913,6 +935,7 @@ func CrossJoin7[A, B, C, D, E, F, G any](listA []A, listB []B, listC []C, listD
|
||||
// CrossJoin8 combines every items from one list with every items from others.
|
||||
// It is the cartesian product of lists received as arguments.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/0k1l2m3n4o5
|
||||
func CrossJoin8[A, B, C, D, E, F, G, H any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H) []Tuple8[A, B, C, D, E, F, G, H] {
|
||||
return CrossJoinBy8(listA, listB, listC, listD, listE, listF, listG, listH, T8[A, B, C, D, E, F, G, H])
|
||||
}
|
||||
@@ -920,6 +943,7 @@ func CrossJoin8[A, B, C, D, E, F, G, H any](listA []A, listB []B, listC []C, lis
|
||||
// CrossJoin9 combines every items from one list with every items from others.
|
||||
// It is the cartesian product of lists received as arguments.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/6p7q8r9s0t1
|
||||
func CrossJoin9[A, B, C, D, E, F, G, H, I any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, listI []I) []Tuple9[A, B, C, D, E, F, G, H, I] {
|
||||
return CrossJoinBy9(listA, listB, listC, listD, listE, listF, listG, listH, listI, T9[A, B, C, D, E, F, G, H, I])
|
||||
}
|
||||
@@ -928,6 +952,7 @@ func CrossJoin9[A, B, C, D, E, F, G, H, I any](listA []A, listB []B, listC []C,
|
||||
// It is the cartesian product of lists received as arguments. The project function
|
||||
// is used to create the output values.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/8Y7btpvuA-C
|
||||
func CrossJoinBy2[A, B, Out any](listA []A, listB []B, project func(a A, b B) Out) []Out {
|
||||
size := len(listA) * len(listB)
|
||||
if size == 0 {
|
||||
@@ -949,6 +974,7 @@ func CrossJoinBy2[A, B, Out any](listA []A, listB []B, project func(a A, b B) Ou
|
||||
// It is the cartesian product of lists received as arguments. The project function
|
||||
// is used to create the output values.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/3z4y5x6w7v8
|
||||
func CrossJoinBy3[A, B, C, Out any](listA []A, listB []B, listC []C, project func(a A, b B, c C) Out) []Out {
|
||||
size := len(listA) * len(listB) * len(listC)
|
||||
if size == 0 {
|
||||
@@ -972,6 +998,7 @@ func CrossJoinBy3[A, B, C, Out any](listA []A, listB []B, listC []C, project fun
|
||||
// It is the cartesian product of lists received as arguments. The project function
|
||||
// is used to create the output values.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/8b9c0d1e2f3
|
||||
func CrossJoinBy4[A, B, C, D, Out any](listA []A, listB []B, listC []C, listD []D, project func(a A, b B, c C, d D) Out) []Out {
|
||||
size := len(listA) * len(listB) * len(listC) * len(listD)
|
||||
if size == 0 {
|
||||
@@ -997,6 +1024,7 @@ func CrossJoinBy4[A, B, C, D, Out any](listA []A, listB []B, listC []C, listD []
|
||||
// It is the cartesian product of lists received as arguments. The project function
|
||||
// is used to create the output values.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/4g5h6i7j8k9
|
||||
func CrossJoinBy5[A, B, C, D, E, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, project func(a A, b B, c C, d D, e E) Out) []Out {
|
||||
size := len(listA) * len(listB) * len(listC) * len(listD) * len(listE)
|
||||
if size == 0 {
|
||||
@@ -1024,6 +1052,7 @@ func CrossJoinBy5[A, B, C, D, E, Out any](listA []A, listB []B, listC []C, listD
|
||||
// It is the cartesian product of lists received as arguments. The project function
|
||||
// is used to create the output values.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/1l2m3n4o5p6
|
||||
func CrossJoinBy6[A, B, C, D, E, F, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, project func(a A, b B, c C, d D, e E, f F) Out) []Out {
|
||||
size := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF)
|
||||
if size == 0 {
|
||||
@@ -1053,6 +1082,7 @@ func CrossJoinBy6[A, B, C, D, E, F, Out any](listA []A, listB []B, listC []C, li
|
||||
// It is the cartesian product of lists received as arguments. The project function
|
||||
// is used to create the output values.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/7q8r9s0t1u2
|
||||
func CrossJoinBy7[A, B, C, D, E, F, G, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, project func(a A, b B, c C, d D, e E, f F, g G) Out) []Out {
|
||||
size := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF) * len(listG)
|
||||
if size == 0 {
|
||||
@@ -1084,6 +1114,7 @@ func CrossJoinBy7[A, B, C, D, E, F, G, Out any](listA []A, listB []B, listC []C,
|
||||
// It is the cartesian product of lists received as arguments. The project function
|
||||
// is used to create the output values.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/3v4w5x6y7z8
|
||||
func CrossJoinBy8[A, B, C, D, E, F, G, H, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, project func(a A, b B, c C, d D, e E, f F, g G, h H) Out) []Out {
|
||||
size := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF) * len(listG) * len(listH)
|
||||
if size == 0 {
|
||||
@@ -1117,6 +1148,7 @@ func CrossJoinBy8[A, B, C, D, E, F, G, H, Out any](listA []A, listB []B, listC [
|
||||
// It is the cartesian product of lists received as arguments. The project function
|
||||
// is used to create the output values.
|
||||
// It returns an empty list if a list is empty.
|
||||
// Play: https://go.dev/play/p/9a0b1c2d3e4
|
||||
func CrossJoinBy9[A, B, C, D, E, F, G, H, I, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, listI []I, project func(a A, b B, c C, d D, e E, f F, g G, h H, i I) Out) []Out {
|
||||
size := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF) * len(listG) * len(listH) * len(listI)
|
||||
if size == 0 {
|
||||
|
@@ -3,28 +3,33 @@ package lo
|
||||
import "reflect"
|
||||
|
||||
// IsNil checks if a value is nil or if it's a reference type with a nil underlying value.
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func IsNil(x any) bool {
|
||||
defer func() { recover() }() // nolint:errcheck
|
||||
return x == nil || reflect.ValueOf(x).IsNil()
|
||||
}
|
||||
|
||||
// IsNotNil checks if a value is not nil or if it's not a reference type with a nil underlying value.
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func IsNotNil(x any) bool {
|
||||
return !IsNil(x)
|
||||
}
|
||||
|
||||
// ToPtr returns a pointer copy of value.
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func ToPtr[T any](x T) *T {
|
||||
return &x
|
||||
}
|
||||
|
||||
// Nil returns a nil pointer of type.
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func Nil[T any]() *T {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EmptyableToPtr returns a pointer copy of value if it's nonzero.
|
||||
// Otherwise, returns nil pointer.
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func EmptyableToPtr[T any](x T) *T {
|
||||
// 🤮
|
||||
isZero := reflect.ValueOf(&x).Elem().IsZero()
|
||||
@@ -36,6 +41,7 @@ func EmptyableToPtr[T any](x T) *T {
|
||||
}
|
||||
|
||||
// FromPtr returns the pointer value or empty.
|
||||
// Play: https://go.dev/play/p/mhD9CwO3X0m
|
||||
func FromPtr[T any](x *T) T {
|
||||
if x == nil {
|
||||
return Empty[T]()
|
||||
@@ -45,6 +51,7 @@ func FromPtr[T any](x *T) T {
|
||||
}
|
||||
|
||||
// FromPtrOr returns the pointer value or the fallback value.
|
||||
// Play: https://go.dev/play/p/mhD9CwO3X0m
|
||||
func FromPtrOr[T any](x *T, fallback T) T {
|
||||
if x == nil {
|
||||
return fallback
|
||||
@@ -54,6 +61,7 @@ func FromPtrOr[T any](x *T, fallback T) T {
|
||||
}
|
||||
|
||||
// ToSlicePtr returns a slice of pointer copy of value.
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func ToSlicePtr[T any](collection []T) []*T {
|
||||
result := make([]*T, len(collection))
|
||||
|
||||
@@ -65,6 +73,7 @@ func ToSlicePtr[T any](collection []T) []*T {
|
||||
|
||||
// FromSlicePtr returns a slice with the pointer values.
|
||||
// Returns a zero value in case of a nil pointer element.
|
||||
// Play: https://go.dev/play/p/lbunFvzlUDX
|
||||
func FromSlicePtr[T any](collection []*T) []T {
|
||||
return Map(collection, func(x *T, _ int) T {
|
||||
if x == nil {
|
||||
@@ -86,6 +95,7 @@ func FromSlicePtrOr[T any](collection []*T, fallback T) []T {
|
||||
}
|
||||
|
||||
// ToAnySlice returns a slice with all elements mapped to `any` type
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func ToAnySlice[T any](collection []T) []any {
|
||||
result := make([]any, len(collection))
|
||||
for i := range collection {
|
||||
@@ -96,6 +106,7 @@ func ToAnySlice[T any](collection []T) []any {
|
||||
|
||||
// FromAnySlice returns an `any` slice with all elements mapped to a type.
|
||||
// Returns false in case of type conversion failure.
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func FromAnySlice[T any](in []any) (out []T, ok bool) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -112,24 +123,28 @@ func FromAnySlice[T any](in []any) (out []T, ok bool) {
|
||||
}
|
||||
|
||||
// Empty returns the zero value (https://go.dev/ref/spec#The_zero_value).
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func Empty[T any]() T {
|
||||
var zero T
|
||||
return zero
|
||||
}
|
||||
|
||||
// IsEmpty returns true if argument is a zero value.
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func IsEmpty[T comparable](v T) bool {
|
||||
var zero T
|
||||
return zero == v
|
||||
}
|
||||
|
||||
// IsNotEmpty returns true if argument is not a zero value.
|
||||
// Play: https://go.dev/play/p/P2sD0PMXw4F
|
||||
func IsNotEmpty[T comparable](v T) bool {
|
||||
var zero T
|
||||
return zero != v
|
||||
}
|
||||
|
||||
// Coalesce returns the first non-empty arguments. Arguments must be comparable.
|
||||
// Play: https://go.dev/play/p/Gyo9otyvFHH
|
||||
func Coalesce[T comparable](values ...T) (result T, ok bool) {
|
||||
for i := range values {
|
||||
if values[i] != result {
|
||||
@@ -143,12 +158,14 @@ func Coalesce[T comparable](values ...T) (result T, ok bool) {
|
||||
}
|
||||
|
||||
// CoalesceOrEmpty returns the first non-empty arguments. Arguments must be comparable.
|
||||
// Play: https://go.dev/play/p/Gyo9otyvFHH
|
||||
func CoalesceOrEmpty[T comparable](v ...T) T {
|
||||
result, _ := Coalesce(v...)
|
||||
return result
|
||||
}
|
||||
|
||||
// CoalesceSlice returns the first non-zero slice.
|
||||
// Play: https://go.dev/play/p/Gyo9otyvFHH
|
||||
func CoalesceSlice[T any](v ...[]T) ([]T, bool) {
|
||||
for i := range v {
|
||||
if v[i] != nil && len(v[i]) > 0 {
|
||||
@@ -159,6 +176,7 @@ func CoalesceSlice[T any](v ...[]T) ([]T, bool) {
|
||||
}
|
||||
|
||||
// CoalesceSliceOrEmpty returns the first non-zero slice.
|
||||
// Play: https://go.dev/play/p/Gyo9otyvFHH
|
||||
func CoalesceSliceOrEmpty[T any](v ...[]T) []T {
|
||||
for i := range v {
|
||||
if v[i] != nil && len(v[i]) > 0 {
|
||||
@@ -169,6 +187,7 @@ func CoalesceSliceOrEmpty[T any](v ...[]T) []T {
|
||||
}
|
||||
|
||||
// CoalesceMap returns the first non-zero map.
|
||||
// Play: https://go.dev/play/p/Gyo9otyvFHH
|
||||
func CoalesceMap[K comparable, V any](v ...map[K]V) (map[K]V, bool) {
|
||||
for i := range v {
|
||||
if v[i] != nil && len(v[i]) > 0 {
|
||||
@@ -179,6 +198,7 @@ func CoalesceMap[K comparable, V any](v ...map[K]V) (map[K]V, bool) {
|
||||
}
|
||||
|
||||
// CoalesceMapOrEmpty returns the first non-zero map.
|
||||
// Play: https://go.dev/play/p/Gyo9otyvFHH
|
||||
func CoalesceMapOrEmpty[K comparable, V any](v ...map[K]V) map[K]V {
|
||||
for i := range v {
|
||||
if v[i] != nil && len(v[i]) > 0 {
|
||||
|
8
types.go
8
types.go
@@ -13,6 +13,7 @@ type Tuple2[A, B any] struct {
|
||||
}
|
||||
|
||||
// Unpack returns values contained in tuple.
|
||||
// Play: https://go.dev/play/p/yrtn7QJTmL_E
|
||||
func (t Tuple2[A, B]) Unpack() (A, B) {
|
||||
return t.A, t.B
|
||||
}
|
||||
@@ -25,6 +26,7 @@ type Tuple3[A, B, C any] struct {
|
||||
}
|
||||
|
||||
// Unpack returns values contained in tuple.
|
||||
// Play: https://go.dev/play/p/yrtn7QJTmL_E
|
||||
func (t Tuple3[A, B, C]) Unpack() (A, B, C) {
|
||||
return t.A, t.B, t.C
|
||||
}
|
||||
@@ -38,6 +40,7 @@ type Tuple4[A, B, C, D any] struct {
|
||||
}
|
||||
|
||||
// Unpack returns values contained in tuple.
|
||||
// Play: https://go.dev/play/p/yrtn7QJTmL_E
|
||||
func (t Tuple4[A, B, C, D]) Unpack() (A, B, C, D) {
|
||||
return t.A, t.B, t.C, t.D
|
||||
}
|
||||
@@ -52,6 +55,7 @@ type Tuple5[A, B, C, D, E any] struct {
|
||||
}
|
||||
|
||||
// Unpack returns values contained in tuple.
|
||||
// Play: https://go.dev/play/p/7J4KrtgtK3M
|
||||
func (t Tuple5[A, B, C, D, E]) Unpack() (A, B, C, D, E) {
|
||||
return t.A, t.B, t.C, t.D, t.E
|
||||
}
|
||||
@@ -67,6 +71,7 @@ type Tuple6[A, B, C, D, E, F any] struct {
|
||||
}
|
||||
|
||||
// Unpack returns values contained in tuple.
|
||||
// Play: https://go.dev/play/p/7J4KrtgtK3M
|
||||
func (t Tuple6[A, B, C, D, E, F]) Unpack() (A, B, C, D, E, F) {
|
||||
return t.A, t.B, t.C, t.D, t.E, t.F
|
||||
}
|
||||
@@ -83,6 +88,7 @@ type Tuple7[A, B, C, D, E, F, G any] struct {
|
||||
}
|
||||
|
||||
// Unpack returns values contained in tuple.
|
||||
// Play: https://go.dev/play/p/Ow9Zgf_zeiA
|
||||
func (t Tuple7[A, B, C, D, E, F, G]) Unpack() (A, B, C, D, E, F, G) {
|
||||
return t.A, t.B, t.C, t.D, t.E, t.F, t.G
|
||||
}
|
||||
@@ -100,6 +106,7 @@ type Tuple8[A, B, C, D, E, F, G, H any] struct {
|
||||
}
|
||||
|
||||
// Unpack returns values contained in tuple.
|
||||
// Play: https://go.dev/play/p/Ow9Zgf_zeiA
|
||||
func (t Tuple8[A, B, C, D, E, F, G, H]) Unpack() (A, B, C, D, E, F, G, H) {
|
||||
return t.A, t.B, t.C, t.D, t.E, t.F, t.G, t.H
|
||||
}
|
||||
@@ -118,6 +125,7 @@ type Tuple9[A, B, C, D, E, F, G, H, I any] struct {
|
||||
}
|
||||
|
||||
// Unpack returns values contained in tuple.
|
||||
// Play: https://go.dev/play/p/Ow9Zgf_zeiA
|
||||
func (t Tuple9[A, B, C, D, E, F, G, H, I]) Unpack() (A, B, C, D, E, F, G, H, I) {
|
||||
return t.A, t.B, t.C, t.D, t.E, t.F, t.G, t.H, t.I
|
||||
}
|
||||
|
Reference in New Issue
Block a user