1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-15 10:12:29 +08:00

Compare commits

...

5 Commits

Author SHA1 Message Date
dudaodong
089fd4e13c feat: add UnionBy for slice 2022-11-05 19:45:34 +08:00
dudaodong
6c40e02324 refactor: clean code 2022-11-05 19:33:56 +08:00
dudaodong
a270b1b634 feat: make code clear 2022-11-05 17:09:56 +08:00
dudaodong
260fb795d3 feat: add KeyBy for slice 2022-11-05 16:52:31 +08:00
dudaodong
8c036f830c refactor: remove unuseful code 2022-11-05 16:39:42 +08:00
2 changed files with 83 additions and 79 deletions

View File

@@ -36,7 +36,7 @@ func ContainSubSlice[T comparable](slice, subslice []T) bool {
// Chunk creates an slice of elements split into groups the length of size.
func Chunk[T any](slice []T, size int) [][]T {
var result [][]T
result := [][]T{}
if len(slice) == 0 || size <= 0 {
return result
@@ -95,7 +95,8 @@ func Concat[T any](slice []T, values ...[]T) []T {
// Difference creates an slice of whose element in slice but not in comparedSlice
func Difference[T comparable](slice, comparedSlice []T) []T {
var result []T
result := []T{}
for _, v := range slice {
if !Contain(comparedSlice, v) {
result = append(result, v)
@@ -123,7 +124,7 @@ func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(inde
}
//DifferenceWith accepts comparator which is invoked to compare elements of slice to values. The order and references of result values are determined by the first slice. The comparator is invoked with two arguments: (arrVal, othVal).
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T {
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value1, value2 T) bool) []T {
result := make([]T, 0)
getIndex := func(arr []T, item T, comparison func(v1, v2 T) bool) int {
@@ -180,11 +181,8 @@ func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) boo
// Every return true if all of the values in the slice pass the predicate function.
func Every[T any](slice []T, predicate func(index int, item T) bool) bool {
if predicate == nil {
panic("predicate func is missing")
}
var currentLength int
for i, v := range slice {
if predicate(i, v) {
currentLength++
@@ -196,9 +194,6 @@ func Every[T any](slice []T, predicate func(index int, item T) bool) bool {
// None return true if all the values in the slice mismatch the criteria
func None[T any](slice []T, predicate func(index int, item T) bool) bool {
if predicate == nil {
panic("predicate func is missing")
}
var currentLength int
for i, v := range slice {
@@ -212,39 +207,30 @@ func None[T any](slice []T, predicate func(index int, item T) bool) bool {
// Some return true if any of the values in the list pass the predicate function.
func Some[T any](slice []T, predicate func(index int, item T) bool) bool {
if predicate == nil {
panic("predicate func is missing")
}
for i, v := range slice {
if predicate(i, v) {
return true
}
}
return false
}
// Filter iterates over elements of slice, returning an slice of all elements pass the predicate function
func Filter[T any](slice []T, predicate func(index int, item T) bool) []T {
if predicate == nil {
panic("predicate func is missing")
}
result := make([]T, 0)
for i, v := range slice {
if predicate(i, v) {
result = append(result, v)
}
}
return result
}
// Count iterates over elements of slice, returns a count of all matched elements
func Count[T any](slice []T, predicate func(index int, item T) bool) int {
if predicate == nil {
panic("predicate func is missing")
}
if len(slice) == 0 {
return 0
}
@@ -261,10 +247,6 @@ func Count[T any](slice []T, predicate func(index int, item T) bool) int {
// GroupBy iterate over elements of the slice, each element will be group by criteria, returns two slices
func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T) {
if groupFn == nil {
panic("groupFn func is missing")
}
if len(slice) == 0 {
return make([]T, 0), make([]T, 0)
}
@@ -285,11 +267,7 @@ func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T)
}
// GroupWith return a map composed of keys generated from the resultults of running each element of slice thru iteratee.
func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T {
if iteratee == nil {
panic("iteratee func is missing")
}
func GroupWith[T any, U comparable](slice []T, iteratee func(item T) U) map[U][]T {
result := make(map[U][]T)
for _, v := range slice {
@@ -306,10 +284,6 @@ func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T {
// Find iterates over elements of slice, returning the first one that passes a truth test on predicate function.
// If return T is nil then no items matched the predicate func
func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
if predicate == nil {
panic("predicate func is missing")
}
if len(slice) == 0 {
return nil, false
}
@@ -332,10 +306,6 @@ func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
// FindLast iterates over elements of slice from end to begin, returning the first one that passes a truth test on predicate function.
// If return T is nil then no items matched the predicate func
func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
if predicate == nil {
panic("predicate func is missing")
}
if len(slice) == 0 {
return nil, false
}
@@ -408,10 +378,6 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
// ForEach iterates over elements of slice and invokes function for each element
func ForEach[T any](slice []T, iteratee func(index int, item T)) {
if iteratee == nil {
panic("iteratee func is missing")
}
for i, v := range slice {
iteratee(i, v)
}
@@ -419,10 +385,6 @@ func ForEach[T any](slice []T, iteratee func(index int, item T)) {
// Map creates an slice of values by running each element of slice thru iteratee function.
func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
if iteratee == nil {
panic("iteratee func is missing")
}
result := make([]U, len(slice), cap(slice))
for i, v := range slice {
result[i] = iteratee(i, v)
@@ -433,9 +395,6 @@ func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
// Reduce creates an slice of values by running each element of slice thru iteratee function.
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T {
if iteratee == nil {
panic("iteratee func is missing")
}
if len(slice) == 0 {
return initial
@@ -604,12 +563,8 @@ func UpdateAt[T any](slice []T, index int, value T) []T {
// Unique remove duplicate elements in slice.
func Unique[T comparable](slice []T) []T {
if len(slice) == 0 {
return []T{}
}
result := []T{}
// here no use map filter. if use it, the result slice element order is random, not same as origin slice
var result []T
for i := 0; i < len(slice); i++ {
v := slice[i]
skip := true
@@ -629,11 +584,8 @@ func Unique[T comparable](slice []T) []T {
// UniqueBy call iteratee func with every item of slice, then remove duplicated.
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
if len(slice) == 0 {
return []T{}
}
result := []T{}
var result []T
for _, v := range slice {
val := iteratee(v)
result = append(result, val)
@@ -642,20 +594,39 @@ func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
return Unique(result)
}
// Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
// Union creates a slice of unique values, in order, from all given slices.
func Union[T comparable](slices ...[]T) []T {
if len(slices) == 0 {
return []T{}
}
// append all slices, then unique it
var allElements []T
result := []T{}
contain := map[T]struct{}{}
for _, slice := range slices {
allElements = append(allElements, slice...)
for _, item := range slice {
if _, ok := contain[item]; !ok {
contain[item] = struct{}{}
result = append(result, item)
}
}
}
return Unique(allElements)
return result
}
// UnionBy is like Union, what's more it accepts iteratee which is invoked for each element of each slice
func UnionBy[T any, V comparable](predicate func(item T) V, slices ...[]T) []T {
result := []T{}
contain := map[V]struct{}{}
for _, slice := range slices {
for _, item := range slice {
val := predicate(item)
if _, ok := contain[val]; !ok {
contain[val] = struct{}{}
result = append(result, item)
}
}
}
return result
}
// Intersection creates a slice of unique values that included by all slices.
@@ -667,8 +638,6 @@ func Intersection[T comparable](slices ...[]T) []T {
return Unique(slices[0])
}
var result []T
reducer := func(sliceA, sliceB []T) []T {
hashMap := make(map[T]int)
for _, val := range sliceA {
@@ -685,7 +654,7 @@ func Intersection[T comparable](slices ...[]T) []T {
return out
}
result = reducer(slices[0], slices[1])
result := reducer(slices[0], slices[1])
reduceSlice := make([][]T, 2)
for i := 2; i < len(slices); i++ {
@@ -818,14 +787,14 @@ func Without[T comparable](slice []T, values ...T) []T {
return slice
}
out := make([]T, 0, len(slice))
result := make([]T, 0, len(slice))
for _, v := range slice {
if !Contain(values, v) {
out = append(out, v)
result = append(result, v)
}
}
return out
return result
}
// IndexOf returns the index at which the first occurrence of a value is found in a slice or return -1
@@ -854,18 +823,20 @@ func LastIndexOf[T comparable](slice []T, value T) int {
// ToSlicePointer returns a pointer to the slices of a variable parameter transformation
func ToSlicePointer[T any](value ...T) []*T {
out := make([]*T, len(value))
result := make([]*T, len(value))
for i := range value {
out[i] = &value[i]
result[i] = &value[i]
}
return out
return result
}
// ToSlice returns a slices of a variable parameter transformation
func ToSlice[T any](value ...T) []T {
out := make([]T, len(value))
copy(out, value)
return out
result := make([]T, len(value))
copy(result, value)
return result
}
// AppendIfAbsent only absent append the value
@@ -875,3 +846,15 @@ func AppendIfAbsent[T comparable](slice []T, value T) []T {
}
return slice
}
// KeyBy converts a slice to a map based on a callback function
func KeyBy[T any, U comparable](slice []T, iteratee func(item T) U) map[U]T {
result := make(map[U]T, len(slice))
for _, v := range slice {
k := iteratee(v)
result[k] = v
}
return result
}

View File

@@ -428,6 +428,17 @@ func TestUnion(t *testing.T) {
assert.Equal([]int{1, 3, 4, 6}, Union(s1))
}
func TestUnionBy(t *testing.T) {
assert := internal.NewAssert(t, "TestUnionBy")
testFunc := func(i int) int {
return i / 2
}
result := UnionBy(testFunc, []int{0, 1, 2, 3, 4, 5}, []int{0, 2, 10})
assert.Equal(result, []int{0, 2, 4, 10})
}
func TestIntersection(t *testing.T) {
s1 := []int{1, 2, 2, 3}
s2 := []int{1, 2, 3, 4}
@@ -644,3 +655,13 @@ func TestReplaceAll(t *testing.T) {
assert.Equal([]string{"x", "b", "x", "c", "d", "x"}, ReplaceAll(strs, "a", "x"))
assert.Equal([]string{"a", "b", "a", "c", "d", "a"}, ReplaceAll(strs, "e", "x"))
}
func TestKeyBy(t *testing.T) {
assert := internal.NewAssert(t, "TestKeyBy")
result := KeyBy([]string{"a", "ab", "abc"}, func(str string) int {
return len(str)
})
assert.Equal(result, map[int]string{1: "a", 2: "ab", 3: "abc"})
}