diff --git a/README.md b/README.md index 4963d2b8..a087485d 100644 --- a/README.md +++ b/README.md @@ -499,6 +499,8 @@ randomOrder := lo.Shuffle[int]([]int{0, 1, 2, 3, 4, 5}) // []int{1, 4, 0, 3, 5, 2} ``` +[[play](https://go.dev/play/p/Qp73bnTDnc7)] + ### Reverse Reverses array so that the first element becomes the last, the second element becomes the second to last, and so on. @@ -508,6 +510,8 @@ reverseOrder := lo.Reverse[int]([]int{0, 1, 2, 3, 4, 5}) // []int{5, 4, 3, 2, 1, 0} ``` +[[play](https://go.dev/play/p/fhUMLvZ7vS6)] + ### Fill Fills elements of array with `initial` value. @@ -525,6 +529,8 @@ initializedSlice := lo.Fill[foo]([]foo{foo{"a"}, foo{"a"}}, foo{"b"}) // []foo{foo{"b"}, foo{"b"}} ``` +[[play](https://go.dev/play/p/VwR34GzqEub)] + ### Repeat Builds a slice with N copies of initial value. @@ -542,22 +548,26 @@ slice := lo.Repeat[foo](2, foo{"a"}) // []foo{foo{"a"}, foo{"a"}} ``` +[[play](https://go.dev/play/p/g3uHXbmc3b6)] + ### RepeatBy Builds a slice with values returned by N calls of callback. ```go slice := lo.RepeatBy[string](0, func (i int) string { - return strconv.FormatInt(math.Pow(i, 2), 10) + return strconv.FormatInt(int64(math.Pow(float64(i), 2)), 10) }) // []int{} -slice := lo.RepeatBy[string](5, func (i int) string { - return strconv.FormatInt(math.Pow(i, 2), 10) +slice := lo.RepeatBy[string](5, func(i int) string { + return strconv.FormatInt(int64(math.Pow(float64(i), 2)), 10) }) // []int{0, 1, 4, 9, 16} ``` +[[play](https://go.dev/play/p/ozZLCtX_hNU)] + ### KeyBy Transforms a slice or an array of structs to a map based on a pivot callback. @@ -582,6 +592,8 @@ result := lo.KeyBy[string, Character](characters, func(char Character) string { //map[a:{dir:left code:97} d:{dir:right code:100}] ``` +[[play](https://go.dev/play/p/mdaClUAT-zZ)] + ### Associate (alias: SliceToMap) Returns a map containing key-value pairs provided by transform function applied to elements of the given slice. @@ -590,7 +602,7 @@ 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. ```go -in := []*foo{{baz: "apple", bar: 1}, {baz: "banana", bar: 2}}, +in := []*foo{{baz: "apple", bar: 1}, {baz: "banana", bar: 2}} aMap := lo.Associate[*foo, string, int](in, func (f *foo) (string, int) { return f.baz, f.bar @@ -598,6 +610,8 @@ aMap := lo.Associate[*foo, string, int](in, func (f *foo) (string, int) { // map[string][int]{ "apple":1, "banana":2 } ``` +[[play](https://go.dev/play/p/WHa2CfMO3Lr)] + ### Drop Drops n elements from the beginning of a slice or array. @@ -607,6 +621,8 @@ l := lo.Drop[int]([]int{0, 1, 2, 3, 4, 5}, 2) // []int{2, 3, 4, 5} ``` +[[play](https://go.dev/play/p/JswS7vXRJP2)] + ### DropRight Drops n elements from the end of a slice or array. @@ -616,6 +632,8 @@ l := lo.DropRight[int]([]int{0, 1, 2, 3, 4, 5}, 2) // []int{0, 1, 2, 3} ``` +[[play](https://go.dev/play/p/GG0nXkSJJa3)] + ### DropWhile Drop elements from the beginning of a slice or array while the predicate returns true. @@ -627,6 +645,8 @@ l := lo.DropWhile[string]([]string{"a", "aa", "aaa", "aa", "aa"}, func(val strin // []string{"aaa", "aa", "aa"} ``` +[[play](https://go.dev/play/p/7gBPYw2IK16)] + ### DropRightWhile Drop elements from the end of a slice or array while the predicate returns true. @@ -638,6 +658,8 @@ l := lo.DropRightWhile[string]([]string{"a", "aa", "aaa", "aa", "aa"}, func(val // []string{"a", "aa", "aaa"} ``` +[[play](https://go.dev/play/p/3-n71oEC0Hz)] + ### Reject The opposite of Filter, this method returns the elements of collection that predicate does not return truthy for. @@ -649,6 +671,8 @@ odd := lo.Reject[int]([]int{1, 2, 3, 4}, func(x int, _ int) bool { // []int{1, 3} ``` +[[play](https://go.dev/play/p/YkLMODy1WEL)] + ### Count Counts the number of elements in the collection that compare equal to value. @@ -658,6 +682,8 @@ count := lo.Count[int]([]int{1, 5, 1}, 1) // 2 ``` +[[play](https://go.dev/play/p/Y3FlK54yveC)] + ### CountBy Counts the number of elements in the collection for which predicate is true. @@ -669,6 +695,8 @@ count := lo.CountBy[int]([]int{1, 5, 1}, func(i int) bool { // 2 ``` +[[play](https://go.dev/play/p/ByQbNYQQi4X)] + ### Subset Returns a copy of a slice from `offset` up to `length` elements. Like `slice[start:start+length]`, but does not panic on overflow. @@ -686,6 +714,8 @@ sub := lo.Subset(in, -2, math.MaxUint) // []int{3, 4} ``` +[[play](https://go.dev/play/p/tOQu1GhFcog)] + ### Slice Returns a copy of a slice from `start` up to, but not including `end`. Like `slice[start:end]`, but does not panic on overflow. @@ -706,6 +736,8 @@ slice := lo.Slice(in, 4, 3) // []int{} ``` +[[play](https://go.dev/play/p/8XWYhfMMA1h)] + ### Replace Returns a copy of the slice with the first n non-overlapping instances of old replaced by new. @@ -726,6 +758,8 @@ slice := lo.Replace(in, 0, 42, -1) // []int{42, 1, 42, 1, 2, 3, 42} ``` +[[play](https://go.dev/play/p/XfPzmf9gql6)] + ### ReplaceAll Returns a copy of the slice with all non-overlapping instances of old replaced by new. @@ -740,6 +774,8 @@ slice := lo.ReplaceAll(in, -1, 42) // []int{0, 1, 0, 1, 2, 3, 0} ``` +[[play](https://go.dev/play/p/a9xZFUHfYcV)] + ### Compact Returns a slice of all non-zero elements. @@ -751,6 +787,8 @@ slice := lo.Compact[string](in) // []string{"foo", "bar"} ``` +[[play](https://go.dev/play/p/tXiy-iK6PAc)] + ### IsSorted Checks if a slice is sorted. @@ -760,6 +798,8 @@ slice := lo.IsSorted([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) // true ``` +[[play](https://go.dev/play/p/mc3qR-t4mcx)] + ### IsSortedByKey Checks if a slice is sorted by iteratee. @@ -771,15 +811,19 @@ slice := lo.IsSortedByKey([]string{"a", "bb", "ccc"}, func(s string) int { // true ``` +[[play](https://go.dev/play/p/wiG6XyBBu49)] + ### Keys Creates an array of the map keys. ```go keys := lo.Keys[string, int](map[string]int{"foo": 1, "bar": 2}) -// []string{"bar", "foo"} +// []string{"foo", "bar"} ``` +[[play](https://go.dev/play/p/Uu11fHASqrU)] + ### Values Creates an array of the map values. @@ -789,6 +833,8 @@ values := lo.Values[string, int](map[string]int{"foo": 1, "bar": 2}) // []int{1, 2} ``` +[[play](https://go.dev/play/p/nnRTQkzQfF6)] + ### PickBy Returns same map type filtered by given predicate. @@ -800,6 +846,8 @@ m := lo.PickBy[string, int](map[string]int{"foo": 1, "bar": 2, "baz": 3}, func(k // map[string]int{"foo": 1, "baz": 3} ``` +[[play](https://go.dev/play/p/kdg8GR_QMmf)] + ### PickByKeys Returns same map type filtered by given keys. @@ -809,6 +857,8 @@ m := lo.PickByKeys[string, int](map[string]int{"foo": 1, "bar": 2, "baz": 3}, [] // map[string]int{"foo": 1, "baz": 3} ``` +[[play](https://go.dev/play/p/R1imbuci9qU)] + ### PickByValues Returns same map type filtered by given values. @@ -818,6 +868,8 @@ m := lo.PickByValues[string, int](map[string]int{"foo": 1, "bar": 2, "baz": 3}, // map[string]int{"foo": 1, "baz": 3} ``` +[[play](https://go.dev/play/p/1zdzSvbfsJc)] + ### OmitBy Returns same map type filtered by given predicate. @@ -829,6 +881,8 @@ m := lo.OmitBy[string, int](map[string]int{"foo": 1, "bar": 2, "baz": 3}, func(k // map[string]int{"bar": 2} ``` +[[play](https://go.dev/play/p/EtBsR43bdsd)] + ### OmitByKeys Returns same map type filtered by given keys. @@ -838,6 +892,8 @@ m := lo.OmitByKeys[string, int](map[string]int{"foo": 1, "bar": 2, "baz": 3}, [] // map[string]int{"bar": 2} ``` +[[play](https://go.dev/play/p/t1QjCrs-ysk)] + ### OmitByValues Returns same map type filtered by given values. @@ -847,6 +903,8 @@ m := lo.OmitByValues[string, int](map[string]int{"foo": 1, "bar": 2, "baz": 3}, // map[string]int{"bar": 2} ``` +[[play](https://go.dev/play/p/9UYZi-hrs8j)] + ### Entries (alias: ToPairs) Transforms a map into array of key/value pairs. @@ -865,6 +923,8 @@ entries := lo.Entries[string, int](map[string]int{"foo": 1, "bar": 2}) // } ``` +[[play](https://go.dev/play/p/3Dhgx46gawJ)] + ### FromEntries (alias: FromPairs) Transforms an array of key/value pairs into a map. @@ -883,18 +943,22 @@ m := lo.FromEntries[string, int]([]lo.Entry[string, int]{ // map[string]int{"foo": 1, "bar": 2} ``` +[[play](https://go.dev/play/p/oIr5KHFGCEN)] + ### Invert Creates a map composed of the inverted keys and values. If map contains duplicate values, subsequent values overwrite property assignments of previous values. ```go -m1 := lo.Invert[string, int]([map[string]int{"a": 1, "b": 2}) +m1 := lo.Invert[string, int](map[string]int{"a": 1, "b": 2}) // map[int]string{1: "a", 2: "b"} -m2 := lo.Invert[string, int]([map[string]int{"a": 1, "b": 2, "c": 1}) +m2 := lo.Invert[string, int](map[string]int{"a": 1, "b": 2, "c": 1}) // map[int]string{1: "c", 2: "b"} ``` +[[play](https://go.dev/play/p/rFQ4rak6iA1)] + ### Assign Merges multiple maps from left to right. @@ -907,6 +971,8 @@ mergedMaps := lo.Assign[string, int]( // map[string]int{"a": 1, "b": 3, "c": 4} ``` +[[play](https://go.dev/play/p/VhwfJOyxf5o)] + ### MapKeys Manipulates a map keys and transforms it to a map of another type. @@ -918,6 +984,8 @@ m2 := lo.MapKeys[int, int, string](map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(_ i // map[string]int{"1": 1, "2": 2, "3": 3, "4": 4} ``` +[[play](https://go.dev/play/p/9_4WPIqOetJ)] + ### MapValues Manipulates a map values and transforms it to a map of another type. @@ -931,6 +999,8 @@ m2 := lo.MapValues[int, int64, string](m1, func(x int64, _ int) string { // map[int]string{1: "1", 2: "2", 3: "3"} ``` +[[play](https://go.dev/play/p/T_8xAfvcf0W)] + ### MapToSlice Transforms a map into a slice based on specific iteratee. @@ -944,6 +1014,8 @@ s := lo.MapToSlice(m, func(k int, v int64) string { // []string{"1_4", "2_5", "3_6"} ``` +[[play](https://go.dev/play/p/ZuiCZpDt6LD)] + ### Range / RangeFrom / RangeWithSteps Creates an array of numbers (positive and/or negative) progressing from start up to, but not including end. @@ -952,28 +1024,30 @@ Creates an array of numbers (positive and/or negative) progressing from start up result := Range(4) // [0, 1, 2, 3] -result := Range(-4); +result := Range(-4) // [0, -1, -2, -3] -result := RangeFrom(1, 5); -// [1, 2, 3, 4] +result := RangeFrom(1, 5) +// [1, 2, 3, 4, 5] -result := RangeFrom[float64](1.0, 5); -// [1.0, 2.0, 3.0, 4.0] +result := RangeFrom[float64](1.0, 5) +// [1.0, 2.0, 3.0, 4.0, 5.0] -result := RangeWithSteps(0, 20, 5); +result := RangeWithSteps(0, 20, 5) // [0, 5, 10, 15] -result := RangeWithSteps[float32](-1.0, -4.0, -1.0); +result := RangeWithSteps[float32](-1.0, -4.0, -1.0) // [-1.0, -2.0, -3.0] -result := RangeWithSteps(1, 4, -1); +result := RangeWithSteps(1, 4, -1) // [] -result := Range(0); +result := Range(0) // [] ``` +[[play](https://go.dev/play/p/0r6VimXAi9H)] + ### Clamp Clamps number within the inclusive lower and upper bounds. @@ -989,6 +1063,8 @@ r3 := lo.Clamp(42, -10, 10) // 10 ``` +[[play](https://go.dev/play/p/RU4lJNC2hlI)] + ### SumBy Summarizes the values in a collection using the given return value from the iteration function. @@ -1002,6 +1078,8 @@ sum := lo.SumBy(strings, func(item string) int { // 6 ``` +[[play](https://go.dev/play/p/Dz_a_7jN_ca)] + ### Substring Return part of a string. @@ -1017,6 +1095,8 @@ sub := lo.Substring("hello", -2, math.MaxUint) // "lo" ``` +[[play](https://go.dev/play/p/TQlxQi82Lu1)] + ### ChunkString Returns an array of strings split into groups the length of size. If array can't be split evenly, the final chunk will be the remaining elements. @@ -1035,6 +1115,8 @@ lo.ChunkString("1", 2) // []string{"1"} ``` +[[play](https://go.dev/play/p/__FLTuJVz54)] + ### RuneLength An alias to utf8.RuneCountInString which returns the number of runes in string. @@ -1047,6 +1129,8 @@ sub := len("hellô") // 6 ``` +[[play](https://go.dev/play/p/tuhgW_lWY8l)] + ### T2 -> T9 Creates a tuple from a list of values. @@ -1577,6 +1661,8 @@ result := lo.Ternary[string](false, "a", "b") // "b" ``` +[[play](https://go.dev/play/p/t-D7WBL44h2)] + ### TernaryF A 1 line if/else statement whose options are functions. @@ -1598,6 +1684,8 @@ someStr := TernaryF[string](s == nil, func() string { return uuid.New().String() // ef782193-c30c-4e2e-a7ae-f8ab5e125e02 ``` +[[play](https://go.dev/play/p/AO4VW20JoqM)] + ### If / ElseIf / Else ```go @@ -1642,6 +1730,8 @@ result := lo.IfF[int](true, func () int { // 1 ``` +[[play](https://go.dev/play/p/WSw3ApMxhyW)] + ### Switch / Case / Default ```go @@ -1691,6 +1781,8 @@ result := lo.Switch[int, string](1). // "1" ``` +[[play](https://go.dev/play/p/TGbKUMAeRUd)] + ### ToPtr Returns a pointer copy of value. diff --git a/condition.go b/condition.go index 32bc7fbe..1d4e75d2 100644 --- a/condition.go +++ b/condition.go @@ -1,6 +1,7 @@ package lo // Ternary is a 1 line if/else statement. +// Play: https://go.dev/play/p/t-D7WBL44h2 func Ternary[T any](condition bool, ifOutput T, elseOutput T) T { if condition { return ifOutput @@ -10,6 +11,7 @@ func Ternary[T any](condition bool, ifOutput T, elseOutput T) T { } // TernaryF is a 1 line if/else statement whose options are functions +// Play: https://go.dev/play/p/AO4VW20JoqM func TernaryF[T any](condition bool, ifFunc func() T, elseFunc func() T) T { if condition { return ifFunc() @@ -24,6 +26,7 @@ type ifElse[T any] struct { } // If. +// Play: https://go.dev/play/p/WSw3ApMxhyW func If[T any](condition bool, result T) *ifElse[T] { if condition { return &ifElse[T]{result, true} @@ -34,6 +37,7 @@ func If[T any](condition bool, result T) *ifElse[T] { } // IfF. +// Play: https://go.dev/play/p/WSw3ApMxhyW func IfF[T any](condition bool, resultF func() T) *ifElse[T] { if condition { return &ifElse[T]{resultF(), true} @@ -44,6 +48,7 @@ func IfF[T any](condition bool, resultF func() T) *ifElse[T] { } // ElseIf. +// Play: https://go.dev/play/p/WSw3ApMxhyW func (i *ifElse[T]) ElseIf(condition bool, result T) *ifElse[T] { if !i.done && condition { i.result = result @@ -54,6 +59,7 @@ func (i *ifElse[T]) ElseIf(condition bool, result T) *ifElse[T] { } // ElseIfF. +// Play: https://go.dev/play/p/WSw3ApMxhyW func (i *ifElse[T]) ElseIfF(condition bool, resultF func() T) *ifElse[T] { if !i.done && condition { i.result = resultF() @@ -64,6 +70,7 @@ func (i *ifElse[T]) ElseIfF(condition bool, resultF func() T) *ifElse[T] { } // Else. +// Play: https://go.dev/play/p/WSw3ApMxhyW func (i *ifElse[T]) Else(result T) T { if i.done { return i.result @@ -73,6 +80,7 @@ func (i *ifElse[T]) Else(result T) T { } // ElseF. +// Play: https://go.dev/play/p/WSw3ApMxhyW func (i *ifElse[T]) ElseF(resultF func() T) T { if i.done { return i.result @@ -88,6 +96,7 @@ type switchCase[T comparable, R any] struct { } // Switch is a pure functional switch/case/default statement. +// Play: https://go.dev/play/p/TGbKUMAeRUd func Switch[T comparable, R any](predicate T) *switchCase[T, R] { var result R @@ -99,6 +108,7 @@ func Switch[T comparable, R any](predicate T) *switchCase[T, R] { } // Case. +// Play: https://go.dev/play/p/TGbKUMAeRUd func (s *switchCase[T, R]) Case(val T, result R) *switchCase[T, R] { if !s.done && s.predicate == val { s.result = result @@ -109,6 +119,7 @@ func (s *switchCase[T, R]) Case(val T, result R) *switchCase[T, R] { } // CaseF. +// Play: https://go.dev/play/p/TGbKUMAeRUd func (s *switchCase[T, R]) CaseF(val T, cb func() R) *switchCase[T, R] { if !s.done && s.predicate == val { s.result = cb() @@ -119,6 +130,7 @@ func (s *switchCase[T, R]) CaseF(val T, cb func() R) *switchCase[T, R] { } // Default. +// Play: https://go.dev/play/p/TGbKUMAeRUd func (s *switchCase[T, R]) Default(result R) R { if !s.done { s.result = result @@ -128,6 +140,7 @@ func (s *switchCase[T, R]) Default(result R) R { } // DefaultF. +// Play: https://go.dev/play/p/TGbKUMAeRUd func (s *switchCase[T, R]) DefaultF(cb func() R) R { if !s.done { s.result = cb() diff --git a/condition_example_test.go b/condition_example_test.go new file mode 100644 index 00000000..1700967e --- /dev/null +++ b/condition_example_test.go @@ -0,0 +1,489 @@ +package lo + +import ( + "fmt" +) + +func ExampleTernary() { + result := Ternary(true, "a", "b") + + fmt.Printf("%v", result) + // Output: a +} + +func ExampleTernaryF() { + result := TernaryF(true, func() string { return "a" }, func() string { return "b" }) + + fmt.Printf("%v", result) + // Output: a +} + +func ExampleIf() { + result1 := If(true, 1). + ElseIf(false, 2). + Else(3) + + result2 := If(false, 1). + ElseIf(true, 2). + Else(3) + + result3 := If(false, 1). + ElseIf(false, 2). + Else(3) + + result4 := IfF(true, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result5 := IfF(false, func() int { return 1 }). + ElseIfF(true, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result6 := IfF(false, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleIfF() { + result1 := If(true, 1). + ElseIf(false, 2). + Else(3) + + result2 := If(false, 1). + ElseIf(true, 2). + Else(3) + + result3 := If(false, 1). + ElseIf(false, 2). + Else(3) + + result4 := IfF(true, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result5 := IfF(false, func() int { return 1 }). + ElseIfF(true, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result6 := IfF(false, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleifElse_ElseIf() { + result1 := If(true, 1). + ElseIf(false, 2). + Else(3) + + result2 := If(false, 1). + ElseIf(true, 2). + Else(3) + + result3 := If(false, 1). + ElseIf(false, 2). + Else(3) + + result4 := IfF(true, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result5 := IfF(false, func() int { return 1 }). + ElseIfF(true, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result6 := IfF(false, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleifElse_ElseIfF() { + result1 := If(true, 1). + ElseIf(false, 2). + Else(3) + + result2 := If(false, 1). + ElseIf(true, 2). + Else(3) + + result3 := If(false, 1). + ElseIf(false, 2). + Else(3) + + result4 := IfF(true, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result5 := IfF(false, func() int { return 1 }). + ElseIfF(true, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result6 := IfF(false, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleifElse_Else() { + result1 := If(true, 1). + ElseIf(false, 2). + Else(3) + + result2 := If(false, 1). + ElseIf(true, 2). + Else(3) + + result3 := If(false, 1). + ElseIf(false, 2). + Else(3) + + result4 := IfF(true, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result5 := IfF(false, func() int { return 1 }). + ElseIfF(true, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result6 := IfF(false, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleifElse_ElseF() { + result1 := If(true, 1). + ElseIf(false, 2). + Else(3) + + result2 := If(false, 1). + ElseIf(true, 2). + Else(3) + + result3 := If(false, 1). + ElseIf(false, 2). + Else(3) + + result4 := IfF(true, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result5 := IfF(false, func() int { return 1 }). + ElseIfF(true, func() int { return 2 }). + ElseF(func() int { return 3 }) + + result6 := IfF(false, func() int { return 1 }). + ElseIfF(false, func() int { return 2 }). + ElseF(func() int { return 3 }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleSwitch() { + result1 := Switch[int, string](1). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result2 := Switch[int, string](2). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result3 := Switch[int, string](42). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result4 := Switch[int, string](1). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result5 := Switch[int, string](2). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result6 := Switch[int, string](42). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleswitchCase_Case() { + result1 := Switch[int, string](1). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result2 := Switch[int, string](2). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result3 := Switch[int, string](42). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result4 := Switch[int, string](1). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result5 := Switch[int, string](2). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result6 := Switch[int, string](42). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleswitchCase_CaseF() { + result1 := Switch[int, string](1). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result2 := Switch[int, string](2). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result3 := Switch[int, string](42). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result4 := Switch[int, string](1). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result5 := Switch[int, string](2). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result6 := Switch[int, string](42). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleswitchCase_Default() { + result1 := Switch[int, string](1). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result2 := Switch[int, string](2). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result3 := Switch[int, string](42). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result4 := Switch[int, string](1). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result5 := Switch[int, string](2). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result6 := Switch[int, string](42). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} + +func ExampleswitchCase_DefaultF() { + result1 := Switch[int, string](1). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result2 := Switch[int, string](2). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result3 := Switch[int, string](42). + Case(1, "1"). + Case(2, "2"). + Default("3") + + result4 := Switch[int, string](1). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result5 := Switch[int, string](2). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + result6 := Switch[int, string](42). + CaseF(1, func() string { return "1" }). + CaseF(2, func() string { return "2" }). + DefaultF(func() string { return "3" }) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + // Output: + // 1 + // 2 + // 3 + // 1 + // 2 + // 3 +} diff --git a/map.go b/map.go index 7e37ea1c..7915e37c 100644 --- a/map.go +++ b/map.go @@ -1,6 +1,7 @@ package lo // Keys creates an array of the map keys. +// Play: https://go.dev/play/p/Uu11fHASqrU func Keys[K comparable, V any](in map[K]V) []K { result := make([]K, 0, len(in)) @@ -12,6 +13,7 @@ func Keys[K comparable, V any](in map[K]V) []K { } // Values creates an array of the map values. +// Play: https://go.dev/play/p/nnRTQkzQfF6 func Values[K comparable, V any](in map[K]V) []V { result := make([]V, 0, len(in)) @@ -23,6 +25,7 @@ func Values[K comparable, V any](in map[K]V) []V { } // PickBy returns same map type filtered by given predicate. +// Play: https://go.dev/play/p/kdg8GR_QMmf func PickBy[K comparable, V any](in map[K]V, predicate func(K, V) bool) map[K]V { r := map[K]V{} for k, v := range in { @@ -34,6 +37,7 @@ func PickBy[K comparable, V any](in map[K]V, predicate func(K, V) bool) map[K]V } // PickByKeys returns same map type filtered by given keys. +// Play: https://go.dev/play/p/R1imbuci9qU func PickByKeys[K comparable, V any](in map[K]V, keys []K) map[K]V { r := map[K]V{} for k, v := range in { @@ -45,6 +49,7 @@ func PickByKeys[K comparable, V any](in map[K]V, keys []K) map[K]V { } // PickByValues returns same map type filtered by given values. +// Play: https://go.dev/play/p/1zdzSvbfsJc func PickByValues[K comparable, V comparable](in map[K]V, values []V) map[K]V { r := map[K]V{} for k, v := range in { @@ -56,6 +61,7 @@ func PickByValues[K comparable, V comparable](in map[K]V, values []V) map[K]V { } // OmitBy returns same map type filtered by given predicate. +// Play: https://go.dev/play/p/EtBsR43bdsd func OmitBy[K comparable, V any](in map[K]V, predicate func(K, V) bool) map[K]V { r := map[K]V{} for k, v := range in { @@ -67,6 +73,7 @@ func OmitBy[K comparable, V any](in map[K]V, predicate func(K, V) bool) map[K]V } // OmitByKeys returns same map type filtered by given keys. +// Play: https://go.dev/play/p/t1QjCrs-ysk func OmitByKeys[K comparable, V any](in map[K]V, keys []K) map[K]V { r := map[K]V{} for k, v := range in { @@ -78,6 +85,7 @@ func OmitByKeys[K comparable, V any](in map[K]V, keys []K) map[K]V { } // OmitByValues returns same map type filtered by given values. +// Play: https://go.dev/play/p/9UYZi-hrs8j func OmitByValues[K comparable, V comparable](in map[K]V, values []V) map[K]V { r := map[K]V{} for k, v := range in { @@ -89,6 +97,7 @@ func OmitByValues[K comparable, V comparable](in map[K]V, values []V) map[K]V { } // Entries transforms a map into array of key/value pairs. +// Play: func Entries[K comparable, V any](in map[K]V) []Entry[K, V] { entries := make([]Entry[K, V], 0, len(in)) @@ -104,11 +113,13 @@ func Entries[K comparable, V any](in map[K]V) []Entry[K, V] { // ToPairs transforms a map into array of key/value pairs. // Alias of Entries(). +// Play: https://go.dev/play/p/3Dhgx46gawJ func ToPairs[K comparable, V any](in map[K]V) []Entry[K, V] { return Entries(in) } // FromEntries transforms an array of key/value pairs into a map. +// Play: https://go.dev/play/p/oIr5KHFGCEN func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V { out := map[K]V{} @@ -121,6 +132,7 @@ func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V { // FromPairs transforms an array of key/value pairs into a map. // Alias of FromEntries(). +// Play: https://go.dev/play/p/oIr5KHFGCEN func FromPairs[K comparable, V any](entries []Entry[K, V]) map[K]V { return FromEntries(entries) } @@ -128,6 +140,7 @@ func FromPairs[K comparable, V any](entries []Entry[K, V]) map[K]V { // Invert creates a map composed of the inverted keys and values. If map // contains duplicate values, subsequent values overwrite property assignments // of previous values. +// Play: https://go.dev/play/p/rFQ4rak6iA1 func Invert[K comparable, V comparable](in map[K]V) map[V]K { out := map[V]K{} @@ -139,6 +152,7 @@ func Invert[K comparable, V comparable](in map[K]V) map[V]K { } // Assign merges multiple maps from left to right. +// Play: https://go.dev/play/p/VhwfJOyxf5o func Assign[K comparable, V any](maps ...map[K]V) map[K]V { out := map[K]V{} @@ -152,6 +166,7 @@ func Assign[K comparable, V any](maps ...map[K]V) map[K]V { } // MapKeys manipulates a map keys and transforms it to a map of another type. +// Play: https://go.dev/play/p/9_4WPIqOetJ func MapKeys[K comparable, V any, R comparable](in map[K]V, iteratee func(V, K) R) map[R]V { result := map[R]V{} @@ -163,6 +178,7 @@ func MapKeys[K comparable, V any, R comparable](in map[K]V, iteratee func(V, K) } // MapValues manipulates a map values and transforms it to a map of another type. +// Play: https://go.dev/play/p/T_8xAfvcf0W func MapValues[K comparable, V any, R any](in map[K]V, iteratee func(V, K) R) map[K]R { result := map[K]R{} @@ -174,6 +190,7 @@ func MapValues[K comparable, V any, R any](in map[K]V, iteratee func(V, K) R) ma } // MapToSlice transforms a map into a slice based on specific iteratee +// Play: https://go.dev/play/p/ZuiCZpDt6LD func MapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(K, V) R) []R { result := make([]R, 0, len(in)) diff --git a/map_example_test.go b/map_example_test.go new file mode 100644 index 00000000..fb4749f9 --- /dev/null +++ b/map_example_test.go @@ -0,0 +1,171 @@ +package lo + +import ( + "fmt" + "sort" + "strconv" + "strings" +) + +func ExampleKeys() { + kv := map[string]int{"foo": 1, "bar": 2} + + result := Keys(kv) + + sort.StringSlice(result).Sort() + fmt.Printf("%v", result) + // Output: [bar foo] +} + +func ExampleValues() { + kv := map[string]int{"foo": 1, "bar": 2} + + result := Values(kv) + + sort.IntSlice(result).Sort() + fmt.Printf("%v", result) + // Output: [1 2] +} + +func ExamplePickBy() { + kv := map[string]int{"foo": 1, "bar": 2, "baz": 3} + + result := PickBy(kv, func(key string, value int) bool { + return value%2 == 1 + }) + + fmt.Printf("%v %v %v", len(result), result["foo"], result["baz"]) + // Output: 2 1 3 +} + +func ExamplePickByKeys() { + kv := map[string]int{"foo": 1, "bar": 2, "baz": 3} + + result := PickByKeys(kv, []string{"foo", "baz"}) + + fmt.Printf("%v %v %v", len(result), result["foo"], result["baz"]) + // Output: 2 1 3 +} + +func ExamplePickByValues() { + kv := map[string]int{"foo": 1, "bar": 2, "baz": 3} + + result := PickByValues(kv, []int{1, 3}) + + fmt.Printf("%v %v %v", len(result), result["foo"], result["baz"]) + // Output: 2 1 3 +} + +func ExampleOmitBy() { + kv := map[string]int{"foo": 1, "bar": 2, "baz": 3} + + result := OmitBy(kv, func(key string, value int) bool { + return value%2 == 1 + }) + + fmt.Printf("%v", result) + // Output: map[bar:2] +} + +func ExampleOmitByKeys() { + kv := map[string]int{"foo": 1, "bar": 2, "baz": 3} + + result := OmitByKeys(kv, []string{"foo", "baz"}) + + fmt.Printf("%v", result) + // Output: map[bar:2] +} + +func ExampleOmitByValues() { + kv := map[string]int{"foo": 1, "bar": 2, "baz": 3} + + result := OmitByValues(kv, []int{1, 3}) + + fmt.Printf("%v", result) + // Output: map[bar:2] +} + +func ExampleEntries() { + kv := map[string]int{"foo": 1, "bar": 2, "baz": 3} + + result := Entries(kv) + + sort.Slice(result, func(i, j int) bool { + return strings.Compare(result[i].Key, result[j].Key) < 0 + }) + fmt.Printf("%v", result) + // Output: [{bar 2} {baz 3} {foo 1}] +} + +func ExampleFromEntries() { + result := FromEntries([]Entry[string, int]{ + { + Key: "foo", + Value: 1, + }, + { + Key: "bar", + Value: 2, + }, + { + Key: "baz", + Value: 3, + }, + }) + + fmt.Printf("%v %v %v %v", len(result), result["foo"], result["bar"], result["baz"]) + // Output: 3 1 2 3 +} + +func ExampleInvert() { + kv := map[string]int{"foo": 1, "bar": 2, "baz": 3} + + result := Invert(kv) + + fmt.Printf("%v %v %v %v", len(result), result[1], result[2], result[3]) + // Output: 3 foo bar baz +} + +func ExampleAssign() { + result := Assign( + map[string]int{"a": 1, "b": 2}, + map[string]int{"b": 3, "c": 4}, + ) + + fmt.Printf("%v %v %v %v", len(result), result["a"], result["b"], result["c"]) + // Output: 3 1 3 4 +} + +func ExampleMapKeys() { + kv := map[int]int{1: 1, 2: 2, 3: 3, 4: 4} + + result := MapKeys(kv, func(_ int, v int) string { + return strconv.FormatInt(int64(v), 10) + }) + + fmt.Printf("%v %v %v %v %v", len(result), result["1"], result["2"], result["3"], result["4"]) + // Output: 4 1 2 3 4 +} + +func ExampleMapValues() { + kv := map[int]int{1: 1, 2: 2, 3: 3, 4: 4} + + result := MapValues(kv, func(_ int, v int) string { + return strconv.FormatInt(int64(v), 10) + }) + + fmt.Printf("%v %v %v %v %v", len(result), result[1], result[2], result[3], result[4]) + // Output: 4 1 2 3 4 +} + +func ExampleMapToSlice() { + kv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4} + + result := MapToSlice(kv, func(k int, v int64) string { + return fmt.Sprintf("%d_%d", k, v) + }) + + sort.StringSlice(result).Sort() + fmt.Printf("%v", result) + // Output: [1_1 2_2 3_3 4_4] +} diff --git a/math.go b/math.go index 1ce1ebe8..30e7e9ef 100644 --- a/math.go +++ b/math.go @@ -3,6 +3,7 @@ package lo import "golang.org/x/exp/constraints" // Range creates an array of numbers (positive and/or negative) with given length. +// Play: https://go.dev/play/p/0r6VimXAi9H func Range(elementNum int) []int { length := If(elementNum < 0, -elementNum).Else(elementNum) result := make([]int, length) @@ -14,6 +15,7 @@ func Range(elementNum int) []int { } // RangeFrom creates an array of numbers from start with specified length. +// Play: https://go.dev/play/p/0r6VimXAi9H func RangeFrom[T constraints.Integer | constraints.Float](start T, elementNum int) []T { length := If(elementNum < 0, -elementNum).Else(elementNum) result := make([]T, length) @@ -26,6 +28,7 @@ func RangeFrom[T constraints.Integer | constraints.Float](start T, elementNum in // RangeWithSteps creates an array of numbers (positive and/or negative) progressing from start up to, but not including end. // step set to zero will return empty array. +// Play: https://go.dev/play/p/0r6VimXAi9H func RangeWithSteps[T constraints.Integer | constraints.Float](start, end, step T) []T { result := []T{} if start == end || step == 0 { @@ -50,6 +53,7 @@ func RangeWithSteps[T constraints.Integer | constraints.Float](start, end, step } // Clamp clamps number within the inclusive lower and upper bounds. +// Play: https://go.dev/play/p/RU4lJNC2hlI func Clamp[T constraints.Ordered](value T, min T, max T) T { if value < min { return min @@ -59,7 +63,8 @@ func Clamp[T constraints.Ordered](value T, min T, max T) T { return value } -// Summarizes the values in a collection. +// SumBy summarizes the values in a collection using the given return value from the iteration function. If collection is empty 0 is returned. +// Play: https://go.dev/play/p/Dz_a_7jN_ca func SumBy[T any, R constraints.Float | constraints.Integer](collection []T, iteratee func(T) R) R { var sum R = 0 for _, item := range collection { diff --git a/math_example_test.go b/math_example_test.go new file mode 100644 index 00000000..27d467be --- /dev/null +++ b/math_example_test.go @@ -0,0 +1,59 @@ +package lo + +import ( + "fmt" +) + +func ExampleRange() { + result1 := Range(4) + result2 := Range(-4) + result3 := RangeFrom(1, 5) + result4 := RangeFrom(1.0, 5) + result5 := RangeWithSteps(0, 20, 5) + result6 := RangeWithSteps[float32](-1.0, -4.0, -1.0) + result7 := RangeWithSteps(1, 4, -1) + result8 := Range(0) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + fmt.Printf("%v\n", result5) + fmt.Printf("%v\n", result6) + fmt.Printf("%v\n", result7) + fmt.Printf("%v\n", result8) + // Output: + // [0 1 2 3] + // [0 -1 -2 -3] + // [1 2 3 4 5] + // [1 2 3 4 5] + // [0 5 10 15] + // [-1 -2 -3] + // [] + // [] +} + +func ExampleClamp() { + result1 := Clamp(0, -10, 10) + result2 := Clamp(-42, -10, 10) + result3 := Clamp(42, -10, 10) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + // Output: + // 0 + // -10 + // 10 +} + +func ExampleSumBy() { + list := []string{"foo", "bar"} + + result := SumBy(list, func(item string) int { + return len(item) + }) + + fmt.Printf("%v", result) + // Output: 6 +} diff --git a/slice.go b/slice.go index eb83ec9d..516fc8b1 100644 --- a/slice.go +++ b/slice.go @@ -230,6 +230,7 @@ func Flatten[T any](collection [][]T) []T { } // Shuffle returns an array of shuffled values. Uses the Fisher-Yates shuffle algorithm. +// Play: https://go.dev/play/p/Qp73bnTDnc7 func Shuffle[T any](collection []T) []T { rand.Shuffle(len(collection), func(i, j int) { collection[i], collection[j] = collection[j], collection[i] @@ -239,6 +240,7 @@ func Shuffle[T any](collection []T) []T { } // Reverse reverses array so that the first element becomes the last, the second element becomes the second to last, and so on. +// Play: https://go.dev/play/p/fhUMLvZ7vS6 func Reverse[T any](collection []T) []T { length := len(collection) half := length / 2 @@ -252,6 +254,7 @@ func Reverse[T any](collection []T) []T { } // Fill fills elements of array with `initial` value. +// Play: https://go.dev/play/p/VwR34GzqEub func Fill[T Clonable[T]](collection []T, initial T) []T { result := make([]T, 0, len(collection)) @@ -263,6 +266,7 @@ func Fill[T Clonable[T]](collection []T, initial T) []T { } // Repeat builds a slice with N copies of initial value. +// Play: https://go.dev/play/p/g3uHXbmc3b6 func Repeat[T Clonable[T]](count int, initial T) []T { result := make([]T, 0, count) @@ -274,6 +278,7 @@ func Repeat[T Clonable[T]](count int, initial T) []T { } // RepeatBy builds a slice with values returned by N calls of callback. +// Play: https://go.dev/play/p/ozZLCtX_hNU func RepeatBy[T any](count int, predicate func(int) T) []T { result := make([]T, 0, count) @@ -285,6 +290,7 @@ func RepeatBy[T any](count int, predicate func(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 func KeyBy[K comparable, V any](collection []V, iteratee func(V) K) map[K]V { result := make(map[K]V, len(collection)) @@ -299,6 +305,7 @@ func KeyBy[K comparable, V any](collection []V, iteratee func(V) K) map[K]V { // Associate returns a map containing key-value pairs provided by transform function applied to elements of the given slice. // 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. +// Play: https://go.dev/play/p/WHa2CfMO3Lr func Associate[T any, K comparable, V any](collection []T, transform func(T) (K, V)) map[K]V { result := make(map[K]V) @@ -314,11 +321,13 @@ func Associate[T any, K comparable, V any](collection []T, transform func(T) (K, // 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. // Alias of Associate(). +// Play: https://go.dev/play/p/WHa2CfMO3Lr func SliceToMap[T any, K comparable, V any](collection []T, transform func(T) (K, V)) map[K]V { return Associate(collection, transform) } // Drop drops n elements from the beginning of a slice or array. +// Play: https://go.dev/play/p/JswS7vXRJP2 func Drop[T any](collection []T, n int) []T { if len(collection) <= n { return make([]T, 0) @@ -329,7 +338,19 @@ func Drop[T any](collection []T, n int) []T { return append(result, collection[n:]...) } +// DropRight drops n elements from the end of a slice or array. +// Play: https://go.dev/play/p/GG0nXkSJJa3 +func DropRight[T any](collection []T, n int) []T { + if len(collection) <= n { + return []T{} + } + + result := make([]T, 0, len(collection)-n) + return append(result, collection[:len(collection)-n]...) +} + // DropWhile drops elements from the beginning of a slice or array while the predicate returns true. +// Play: https://go.dev/play/p/7gBPYw2IK16 func DropWhile[T any](collection []T, predicate func(T) bool) []T { i := 0 for ; i < len(collection); i++ { @@ -342,17 +363,8 @@ func DropWhile[T any](collection []T, predicate func(T) bool) []T { return append(result, collection[i:]...) } -// DropRight drops n elements from the end of a slice or array. -func DropRight[T any](collection []T, n int) []T { - if len(collection) <= n { - return []T{} - } - - result := make([]T, 0, len(collection)-n) - return append(result, collection[:len(collection)-n]...) -} - // DropRightWhile drops elements from the end of a slice or array while the predicate returns true. +// Play: https://go.dev/play/p/3-n71oEC0Hz func DropRightWhile[T any](collection []T, predicate func(T) bool) []T { i := len(collection) - 1 for ; i >= 0; i-- { @@ -366,6 +378,7 @@ func DropRightWhile[T any](collection []T, predicate func(T) bool) []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 func Reject[V any](collection []V, predicate func(V, int) bool) []V { result := []V{} @@ -379,6 +392,7 @@ func Reject[V any](collection []V, predicate func(V, int) bool) []V { } // Count counts the number of elements in the collection that compare equal to value. +// Play: https://go.dev/play/p/Y3FlK54yveC func Count[T comparable](collection []T, value T) (count int) { for _, item := range collection { if item == value { @@ -390,6 +404,7 @@ func Count[T comparable](collection []T, value T) (count int) { } // CountBy counts the number of elements in the collection for which predicate is true. +// Play: https://go.dev/play/p/ByQbNYQQi4X func CountBy[T any](collection []T, predicate func(T) bool) (count int) { for _, item := range collection { if predicate(item) { @@ -401,6 +416,7 @@ func CountBy[T any](collection []T, predicate func(T) bool) (count int) { } // Subset returns a copy of a slice from `offset` up to `length` elements. Like `slice[start:start+length]`, but does not panic on overflow. +// Play: https://go.dev/play/p/tOQu1GhFcog func Subset[T any](collection []T, offset int, length uint) []T { size := len(collection) @@ -423,6 +439,7 @@ func Subset[T any](collection []T, offset int, length uint) []T { } // Slice returns a copy of a slice from `start` up to, but not including `end`. Like `slice[start:end]`, but does not panic on overflow. +// Play: https://go.dev/play/p/8XWYhfMMA1h func Slice[T any](collection []T, start int, end int) []T { size := len(collection) @@ -442,6 +459,7 @@ func Slice[T any](collection []T, start int, end int) []T { } // Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new. +// Play: https://go.dev/play/p/XfPzmf9gql6 func Replace[T comparable](collection []T, old T, new T, n int) []T { result := make([]T, len(collection)) copy(result, collection) @@ -457,11 +475,13 @@ func Replace[T comparable](collection []T, old T, new T, n int) []T { } // ReplaceAll returns a copy of the slice with all non-overlapping instances of old replaced by new. +// Play: https://go.dev/play/p/a9xZFUHfYcV func ReplaceAll[T comparable](collection []T, old T, new T) []T { return Replace(collection, old, new, -1) } // Compact returns a slice of all non-zero elements. +// Play: https://go.dev/play/p/tXiy-iK6PAc func Compact[T comparable](collection []T) []T { var zero T @@ -477,6 +497,7 @@ func Compact[T comparable](collection []T) []T { } // IsSorted checks if a slice is sorted. +// Play: https://go.dev/play/p/mc3qR-t4mcx func IsSorted[T constraints.Ordered](collection []T) bool { for i := 1; i < len(collection); i++ { if collection[i-1] > collection[i] { @@ -488,6 +509,7 @@ func IsSorted[T constraints.Ordered](collection []T) bool { } // IsSortedByKey checks if a slice is sorted by iteratee. +// Play: https://go.dev/play/p/wiG6XyBBu49 func IsSortedByKey[T any, K constraints.Ordered](collection []T, iteratee func(T) K) bool { size := len(collection) diff --git a/slice_example_test.go b/slice_example_test.go index 9214da3f..6ba2b1c3 100644 --- a/slice_example_test.go +++ b/slice_example_test.go @@ -2,6 +2,7 @@ package lo import ( "fmt" + "math" "strconv" ) @@ -176,3 +177,219 @@ func ExampleFlatten() { fmt.Printf("%v", result) // Output: [0 1 2 3 4 5] } + +func ExampleShuffle() { + list := []int{0, 1, 2, 3, 4, 5} + + result := Shuffle(list) + + fmt.Printf("%v", result) +} + +func ExampleReverse() { + list := []int{0, 1, 2, 3, 4, 5} + + result := Reverse(list) + + fmt.Printf("%v", result) + // Output: [5 4 3 2 1 0] +} + +func ExampleFill() { + list := []foo{foo{"a"}, foo{"a"}} + + result := Fill[foo](list, foo{"b"}) + + fmt.Printf("%v", result) + // Output: [{b} {b}] +} + +func ExampleRepeat() { + result := Repeat[foo](2, foo{"a"}) + + fmt.Printf("%v", result) + // Output: [{a} {a}] +} + +func ExampleRepeatBy() { + result := RepeatBy[string](5, func(i int) string { + return strconv.FormatInt(int64(math.Pow(float64(i), 2)), 10) + }) + + fmt.Printf("%v", result) + // Output: [0 1 4 9 16] +} + +func ExampleKeyBy() { + list := []string{"a", "aa", "aaa"} + + result := KeyBy[int, string](list, func(str string) int { + return len(str) + }) + + fmt.Printf("%v", result) + // Output: map[1:a 2:aa 3:aaa] +} + +func ExampleAssociate() { + list := []string{"a", "aa", "aaa"} + + result := Associate(list, func(str string) (string, int) { + return str, len(str) + }) + + fmt.Printf("%v", result) + // Output: map[a:1 aa:2 aaa:3] +} + +func ExampleDrop() { + list := []int{0, 1, 2, 3, 4, 5} + + result := Drop(list, 2) + + fmt.Printf("%v", result) + // Output: [2 3 4 5] +} + +func ExampleDropRight() { + list := []int{0, 1, 2, 3, 4, 5} + + result := DropRight(list, 2) + + fmt.Printf("%v", result) + // Output: [0 1 2 3] +} + +func ExampleDropWhile() { + list := []int{0, 1, 2, 3, 4, 5} + + result := DropWhile(list, func(val int) bool { + return val < 2 + }) + + fmt.Printf("%v", result) + // Output: [2 3 4 5] +} + +func ExampleDropRightWhile() { + list := []int{0, 1, 2, 3, 4, 5} + + result := DropRightWhile(list, func(val int) bool { + return val > 2 + }) + + fmt.Printf("%v", result) + // Output: [0 1 2] +} + +func ExampleReject() { + list := []int{0, 1, 2, 3, 4, 5} + + result := Reject(list, func(x int, _ int) bool { + return x%2 == 0 + }) + + fmt.Printf("%v", result) + // Output: [1 3 5] +} + +func ExampleCount() { + list := []int{0, 1, 2, 3, 4, 5, 0, 1, 2, 3} + + result := Count(list, 2) + + fmt.Printf("%v", result) + // Output: 2 +} + +func ExampleCountBy() { + list := []int{0, 1, 2, 3, 4, 5, 0, 1, 2, 3} + + result := CountBy(list, func(i int) bool { + return i < 4 + }) + + fmt.Printf("%v", result) + // Output: 8 +} + +func ExampleSubset() { + list := []int{0, 1, 2, 3, 4, 5} + + result := Subset(list, 2, 3) + + fmt.Printf("%v", result) + // Output: [2 3 4] +} + +func ExampleSlice() { + list := []int{0, 1, 2, 3, 4, 5} + + result := Slice(list, 1, 4) + fmt.Printf("%v\n", result) + + result = Slice(list, 4, 1) + fmt.Printf("%v\n", result) + + result = Slice(list, 4, 5) + fmt.Printf("%v\n", result) + + // Output: + // [1 2 3] + // [] + // [4] +} + +func ExampleReplace() { + list := []int{0, 1, 0, 1, 2, 3, 0} + + result := Replace(list, 0, 42, 1) + fmt.Printf("%v\n", result) + + result = Replace(list, -1, 42, 1) + fmt.Printf("%v\n", result) + + result = Replace(list, 0, 42, 2) + fmt.Printf("%v\n", result) + + result = Replace(list, 0, 42, -1) + fmt.Printf("%v\n", result) + + // Output: + // [42 1 0 1 2 3 0] + // [0 1 0 1 2 3 0] + // [42 1 42 1 2 3 0] + // [42 1 42 1 2 3 42] +} + +func ExampleReplaceAll() { + list := []string{"", "foo", "", "bar", ""} + + result := Compact(list) + + fmt.Printf("%v", result) + + // Output: [foo bar] +} + +func ExampleIsSorted() { + list := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + + result := IsSorted(list) + + fmt.Printf("%v", result) + + // Output: true +} + +func ExampleIsSortedByKey() { + list := []string{"a", "bb", "ccc"} + + result := IsSortedByKey(list, func(s string) int { + return len(s) + }) + + fmt.Printf("%v", result) + + // Output: true +} diff --git a/slice_test.go b/slice_test.go index e3bad136..b3cfc541 100644 --- a/slice_test.go +++ b/slice_test.go @@ -10,14 +10,6 @@ import ( "github.com/stretchr/testify/assert" ) -type foo struct { - bar string -} - -func (f foo) Clone() foo { - return foo{f.bar} -} - func TestFilter(t *testing.T) { t.Parallel() is := assert.New(t) diff --git a/string.go b/string.go index 90c42749..a63167cb 100644 --- a/string.go +++ b/string.go @@ -5,6 +5,7 @@ import ( ) // Substring return part of a string. +// Play: https://go.dev/play/p/TQlxQi82Lu1 func Substring[T ~string](str T, offset int, length uint) T { size := len(str) @@ -28,6 +29,7 @@ func Substring[T ~string](str T, offset int, length uint) T { // ChunkString returns an array of strings 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/__FLTuJVz54 func ChunkString[T ~string](str T, size int) []T { if size <= 0 { panic("lo.ChunkString: Size parameter must be greater than 0") @@ -57,6 +59,7 @@ func ChunkString[T ~string](str T, size int) []T { } // RuneLength is an alias to utf8.RuneCountInString which returns the number of runes in string. +// Play: https://go.dev/play/p/tuhgW_lWY8l func RuneLength(str string) int { return utf8.RuneCountInString(str) } diff --git a/string_example_test.go b/string_example_test.go new file mode 100644 index 00000000..ad93fda0 --- /dev/null +++ b/string_example_test.go @@ -0,0 +1,48 @@ +package lo + +import ( + "fmt" + "math" +) + +func ExampleSubstring() { + result1 := Substring("hello", 2, 3) + result2 := Substring("hello", -4, 3) + result3 := Substring("hello", -2, math.MaxUint) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + // Output: + // llo + // ell + // lo +} + +func ExampleChunkString() { + result1 := ChunkString("123456", 2) + result2 := ChunkString("1234567", 2) + result3 := ChunkString("", 2) + result4 := ChunkString("1", 2) + + fmt.Printf("%v\n", result1) + fmt.Printf("%v\n", result2) + fmt.Printf("%v\n", result3) + fmt.Printf("%v\n", result4) + // Output: + // [12 34 56] + // [12 34 56 7] + // [] + // [1] +} + +func ExampleRuneLength() { + result1, chars1 := RuneLength("hellô"), len("hellô") + result2, chars2 := RuneLength("🤘"), len("🤘") + + fmt.Printf("%v %v\n", result1, chars1) + fmt.Printf("%v %v\n", result2, chars2) + // Output: + // 5 6 + // 1 4 +} diff --git a/test.go b/test.go index 55319c24..26db4c25 100644 --- a/test.go +++ b/test.go @@ -22,3 +22,11 @@ func testWithTimeout(t *testing.T, timeout time.Duration) { } }() } + +type foo struct { + bar string +} + +func (f foo) Clone() foo { + return foo{f.bar} +}