-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
250 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package xlo_test | ||
|
||
import ( | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/samber/lo" | ||
|
||
"github.com/v8fg/kit4go/xlo" | ||
) | ||
|
||
func BenchmarkFindUniquesInt(b *testing.B) { | ||
testSet := [][]int{ | ||
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, | ||
{1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2}, | ||
{1, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 2}, | ||
} | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
for j := 0; j < len(testSet); j++ { | ||
xlo.Uniq(testSet[j]) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkFindUniquesStr(b *testing.B) { | ||
testSet := [][]string{ | ||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"}, | ||
{"1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2"}, | ||
{"1", "2", "2", "2", "2", "2", "1", "1", "1", "2", "1", "2"}, | ||
} | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
for j := 0; j < len(testSet); j++ { | ||
xlo.Uniq(testSet[j]) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkLoFindUniquesInt(b *testing.B) { | ||
testSet := [][]int{ | ||
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, | ||
{1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2}, | ||
{1, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 2}, | ||
} | ||
|
||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
for j := 0; j < len(testSet); j++ { | ||
xlo.LoUniq(testSet[j]) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkLoFindUniquesStr(b *testing.B) { | ||
testSet := [][]string{ | ||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"}, | ||
{"1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2"}, | ||
{"1", "2", "2", "2", "2", "2", "1", "1", "1", "2", "1", "2"}, | ||
} | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
for j := 0; j < len(testSet); j++ { | ||
xlo.LoUniq(testSet[j]) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkLoMap(b *testing.B) { | ||
original := lo.Range(1_024) | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
xlo.LoMap(original, func(item int, index int) string { | ||
return strconv.FormatInt(int64(item), 10) | ||
}) | ||
} | ||
} | ||
|
||
func BenchmarkLopMap(b *testing.B) { | ||
original := lo.Range(1_024) | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
xlo.LopMap(original, func(item int, index int) string { | ||
return strconv.FormatInt(int64(item), 10) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package xlo | ||
|
||
import ( | ||
"github.com/samber/lo" | ||
lop "github.com/samber/lo/parallel" | ||
) | ||
|
||
// Maximum average load of a bucket that triggers growth is 6.5. | ||
// Represent as loadFactorNum/loadFactorDen, to allow integer math. | ||
// loadFactorDen = 2 | ||
// defined in runtime./map.go | ||
const loadFactorNum = 13 | ||
|
||
// Uniq returns a duplicate-free version of an array, in which only the first occurrence of each element is kept. | ||
// The order of result values is determined by the order they occur in the array. | ||
// | ||
// Some optimizations for small capacity temp map, if capacity less than loadFactorNum. | ||
func Uniq[T comparable](collection []T) []T { | ||
size := len(collection) | ||
result := make([]T, 0, size) | ||
var temp map[T]struct{} | ||
if size < loadFactorNum { | ||
temp = map[T]struct{}{} | ||
} else { | ||
temp = make(map[T]struct{}, size) | ||
} | ||
|
||
for _, item := range collection { | ||
if _, ok := temp[item]; !ok { | ||
temp[item] = struct{}{} | ||
result = append(result, item) | ||
} | ||
} | ||
return result | ||
} | ||
|
||
// LoUniq returns a duplicate-free version of an array, in which only the first occurrence of each element is kept. | ||
// The order of result values is determined by the order they occur in the array. | ||
func LoUniq[T comparable](collection []T) []T { | ||
return lo.Uniq(collection) | ||
} | ||
|
||
// LoMap manipulates a slice and transforms it to a slice of another type. | ||
func LoMap[T any, R any](collection []T, iteratee func(item T, index int) R) []R { | ||
return lo.Map(collection, iteratee) | ||
} | ||
|
||
// LopMap manipulates a slice and transforms it to a slice of another type. | ||
// `iteratee` is call in parallel. Result keep the same order. | ||
func LopMap[T any, R any](collection []T, iteratee func(item T, index int) R) []R { | ||
return lop.Map(collection, iteratee) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package xlo_test | ||
|
||
import ( | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/smartystreets/goconvey/convey" | ||
|
||
"github.com/v8fg/kit4go/xlo" | ||
) | ||
|
||
func TestFindUniques(t *testing.T) { | ||
convey.SetDefaultFailureMode(convey.FailureContinues) | ||
convey.Convey("TestFindUniques", t, func() { | ||
convey.Convey("int case", func() { | ||
convey.So(xlo.Uniq([]int{1, 2, 3}), convey.ShouldResemble, []int{1, 2, 3}) | ||
convey.So(xlo.Uniq([]int{1, 2, 2, 3, 1, 2, 1, 2, 2, 3, 1, 2}), convey.ShouldResemble, []int{1, 2, 3}) | ||
convey.So(xlo.Uniq([]int{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}), convey.ShouldResemble, []int{1}) | ||
}) | ||
convey.Convey("string case", func() { | ||
convey.So(xlo.Uniq([]string{"1", "2", "3"}), convey.ShouldResemble, []string{"1", "2", "3"}) | ||
convey.So(xlo.Uniq([]string{"1", "2", "1", "2", "1"}), convey.ShouldResemble, []string{"1", "2"}) | ||
}) | ||
|
||
}) | ||
} | ||
|
||
func TestLoFindUniques(t *testing.T) { | ||
convey.SetDefaultFailureMode(convey.FailureContinues) | ||
convey.Convey("TestLoFindUniques", t, func() { | ||
convey.Convey("int case", func() { | ||
convey.So(xlo.LoUniq([]int{1, 2, 3}), convey.ShouldResemble, []int{1, 2, 3}) | ||
convey.So(xlo.LoUniq([]int{1, 2, 2, 3, 1, 2, 1, 2, 2, 3, 1, 2}), convey.ShouldResemble, []int{1, 2, 3}) | ||
convey.So(xlo.LoUniq([]int{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}), convey.ShouldResemble, []int{1}) | ||
}) | ||
convey.Convey("string case", func() { | ||
convey.So(xlo.LoUniq([]string{"1", "2", "3"}), convey.ShouldResemble, []string{"1", "2", "3"}) | ||
convey.So(xlo.LoUniq([]string{"1", "2", "1", "2", "1"}), convey.ShouldResemble, []string{"1", "2"}) | ||
}) | ||
}) | ||
} | ||
|
||
func TestLoMap(t *testing.T) { | ||
convey.SetDefaultFailureMode(convey.FailureContinues) | ||
convey.Convey("TestLoMap", t, func() { | ||
original := []int{1, 2, 3} | ||
ret := xlo.LoMap(original, func(item int, index int) string { | ||
return strconv.FormatInt(int64(item), 10) | ||
}) | ||
convey.So(ret, convey.ShouldResemble, []string{"1", "2", "3"}) | ||
}) | ||
} | ||
|
||
func TestLopMap(t *testing.T) { | ||
convey.SetDefaultFailureMode(convey.FailureContinues) | ||
convey.Convey("TestLopMap", t, func() { | ||
original := []int{1, 2, 3} | ||
ret := xlo.LopMap(original, func(item int, index int) string { | ||
return strconv.FormatInt(int64(item), 10) | ||
}) | ||
convey.So(ret, convey.ShouldResemble, []string{"1", "2", "3"}) | ||
}) | ||
} |