1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-09 23:22:28 +08:00

fmt: slice.go

This commit is contained in:
dudaodong
2022-01-10 10:27:20 +08:00
23 changed files with 968 additions and 1454 deletions

View File

@@ -11,45 +11,23 @@ import (
"math/rand"
"reflect"
"sort"
"strings"
"unsafe"
)
// Contain check if the value is in the iterable type or not
func Contain(iterableType interface{}, value interface{}) bool {
v := reflect.ValueOf(iterableType)
switch kind := reflect.TypeOf(iterableType).Kind(); kind {
case reflect.Slice, reflect.Array:
for i := 0; i < v.Len(); i++ {
if v.Index(i).Interface() == value {
return true
}
}
case reflect.Map:
if v.MapIndex(reflect.ValueOf(value)).IsValid() {
func Contain[T comparable](slice []T, value T) bool {
for _, v := range slice {
if v == value {
return true
}
case reflect.String:
s := iterableType.(string)
ss, ok := value.(string)
if !ok {
panic("kind mismatch")
}
return strings.Contains(s, ss)
default:
panic(fmt.Sprintf("kind %s is not support", iterableType))
}
return false
}
// Chunk creates an slice of elements split into groups the length of `size`.
func Chunk(slice []interface{}, size int) [][]interface{} {
var res [][]interface{}
// Chunk creates an slice of elements split into groups the length of size.
func Chunk[T any](slice []T, size int) [][]T {
var res [][]T
if len(slice) == 0 || size <= 0 {
return res
@@ -58,7 +36,7 @@ func Chunk(slice []interface{}, size int) [][]interface{} {
length := len(slice)
if size == 1 || size >= length {
for _, v := range slice {
var tmp []interface{}
var tmp []T
tmp = append(tmp, v)
res = append(res, tmp)
}
@@ -80,93 +58,59 @@ func Chunk(slice []interface{}, size int) [][]interface{} {
return res
}
// Difference creates an slice of whose element not included in the other given slice
func Difference(slice1, slice2 interface{}) interface{} {
v := sliceValue(slice1)
var indexes []int
for i := 0; i < v.Len(); i++ {
vi := v.Index(i).Interface()
if !Contain(slice2, vi) {
indexes = append(indexes, i)
// Difference creates an slice of whose element in slice1 but not in slice2
func Difference[T comparable](slice1, slice2 []T) []T {
var res []T
for _, v := range slice1 {
if !Contain(slice2, v) {
res = append(res, v)
}
}
res := reflect.MakeSlice(v.Type(), len(indexes), len(indexes))
for i := range indexes {
res.Index(i).Set(v.Index(indexes[i]))
}
return res.Interface()
return res
}
// Every return true if all of the values in the slice pass the predicate function.
// The function signature should be func(index int, value interface{}) bool .
func Every(slice, function interface{}) bool {
sv := sliceValue(slice)
fn := functionValue(function)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
// The fn function signature should be func(int, T) bool .
func Every[T any](slice []T, fn func(index int, t T) bool) bool {
var currentLength int
for i := 0; i < sv.Len(); i++ {
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
if flag.Bool() {
for i, v := range slice {
if fn(i, v) {
currentLength++
}
}
return currentLength == sv.Len()
return currentLength == len(slice)
}
// None return true if all the values in the slice mismatch the criteria
// The function signature should be func(index int, value interface{}) bool .
func None(slice, function interface{}) bool {
sv := sliceValue(slice)
fn := functionValue(function)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
// The fn function signature should be func(int, T) bool .
func None[T any](slice []T, fn func(index int, t T) bool) bool {
var currentLength int
for i := 0; i < sv.Len(); i++ {
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
if !flag.Bool() {
for i, v := range slice {
if !fn(i, v) {
currentLength++
}
}
return currentLength == sv.Len()
return currentLength == len(slice)
}
// Some return true if any of the values in the list pass the predicate function.
// The function signature should be func(index int, value interface{}) bool .
func Some(slice, function interface{}) bool {
sv := sliceValue(slice)
fn := functionValue(function)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
has := false
for i := 0; i < sv.Len(); i++ {
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
if flag.Bool() {
has = true
// The fn function signature should be func(int, T) bool.
func Some[T any](slice []T, fn func(index int, t T) bool) bool {
for i, v := range slice {
if fn(i, v) {
return true
}
}
return has
return false
}
// Filter iterates over elements of slice, returning an slice of all elements `signature` returns truthy for.
// The fn signature should be func(int, T) bool.
// The fn function signature should be func(int, T) bool.
func Filter[T any](slice []T, fn func(index int, t T) bool) []T {
res := make([]T, 0, 0)
for i, v := range slice {
@@ -179,24 +123,23 @@ func Filter[T any](slice []T, fn func(index int, t T) bool) []T {
// Count iterates over elements of slice, returns a count of all matched elements
// The function signature should be func(index int, value interface{}) bool .
func Count(slice, function interface{}) int {
sv := sliceValue(slice)
fn := functionValue(function)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
func Count[T any](slice []T, fn func(index int, t T) bool) int {
if fn == nil {
panic("fn is missing")
}
var counter int
for i := 0; i < sv.Len(); i++ {
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
if flag.Bool() {
counter++
if len(slice) == 0 {
return 0
}
var count int
for i, v := range slice {
if fn(i, v) {
count++
}
}
return counter
return count
}
// GroupBy iterate over elements of the slice, each element will be group by criteria, returns two slices
@@ -226,31 +169,26 @@ func GroupBy(slice, function interface{}) (interface{}, interface{}) {
}
// Find iterates over elements of slice, returning the first one that passes a truth test on function.
// The function signature should be func(index int, value interface{}) bool .
func Find(slice, function interface{}) (interface{}, bool) {
sv := sliceValue(slice)
fn := functionValue(function)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
// The fn function signature should be func(int, T) bool .
// If return T is nil then no items matched the predicate func
func Find[T any](slice []T, fn func(index int, t T) bool) (*T, bool) {
if len(slice) == 0 {
return nil, false
}
index := -1
for i := 0; i < sv.Len(); i++ {
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
if flag.Bool() {
for i, v := range slice {
if fn(i, v) {
index = i
break
}
}
if index == -1 {
var none interface{}
return none, false
return nil, false
}
return sv.Index(index).Interface(), true
return &slice[index], true
}
// FlattenDeep flattens slice recursive
@@ -278,14 +216,14 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
}
// ForEach iterates over elements of slice and invokes function for each element
// The fn signature should be func(int, T ).
// The fn signature should be func(int, T).
func ForEach[T any](slice []T, fn func(index int, t T)) {
for i, v := range slice {
fn(i, v)
}
}
// Map creates an slice of values by running each element of `slice` thru `function`.
// Map creates an slice of values by running each element of slice thru fn function.
// The fn signature should be func(int, T).
func Map[T any, U any](slice []T, fn func(index int, t T) U) []U {
res := make([]U, len(slice), cap(slice))
@@ -296,40 +234,23 @@ func Map[T any, U any](slice []T, fn func(index int, t T) U) []U {
return res
}
// Reduce creates an slice of values by running each element of `slice` thru `function`.
// The function signature should be func(index int, value1, value2 interface{}) interface{} .
func Reduce(slice, function, zero interface{}) interface{} {
sv := sliceValue(slice)
elementType := sv.Type().Elem()
len := sv.Len()
if len == 0 {
return zero
} else if len == 1 {
return sv.Index(0).Interface()
// Reduce creates an slice of values by running each element of slice thru fn function.
// The fn function signature should be fn func(int, T) T .
func Reduce[T any](slice []T, fn func(index int, t1, t2 T) T, initial T) T {
if len(slice) == 0 {
return initial
}
fn := functionValue(function)
if checkSliceCallbackFuncSignature(fn, elementType, elementType, elementType) {
t := elementType.String()
panic("function param should be of type func(int, " + t + ", " + t + ")" + t)
res := fn(0, initial, slice[0])
tmp := make([]T, 2, 2)
for i := 1; i < len(slice); i++ {
tmp[0] = res
tmp[1] = slice[i]
res = fn(i, tmp[0], tmp[1])
}
var params [3]reflect.Value
params[0] = reflect.ValueOf(0)
params[1] = sv.Index(0)
params[2] = sv.Index(1)
res := fn.Call(params[:])[0]
for i := 2; i < len; i++ {
params[0] = reflect.ValueOf(i)
params[1] = res
params[2] = sv.Index(i)
res = fn.Call(params[:])[0]
}
return res.Interface()
return res
}
// InterfaceSlice convert param to slice of interface.
@@ -504,106 +425,82 @@ func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}
}
// Unique remove duplicate elements in slice.
func Unique(slice interface{}) interface{} {
sv := sliceValue(slice)
if sv.Len() == 0 {
return slice
func Unique[T comparable](slice []T) []T {
if len(slice) == 0 {
return []T{}
}
var temp []interface{}
for i := 0; i < sv.Len(); i++ {
v := sv.Index(i).Interface()
// here no use map filter. if use it, the result slice element order is random, not same as origin slice
var res []T
for i := 0; i < len(slice); i++ {
v := slice[i]
skip := true
for j := range temp {
if v == temp[j] {
for j := range res {
if v == res[j] {
skip = false
break
}
}
if skip {
temp = append(temp, v)
res = append(res, v)
}
}
res := reflect.MakeSlice(sv.Type(), len(temp), len(temp))
for i := 0; i < len(temp); i++ {
res.Index(i).Set(reflect.ValueOf(temp[i]))
}
return res.Interface()
// if use map filter, the result slice element order is random, not same as origin slice
//mp := make(map[interface{}]bool)
//for i := 0; i < sv.Len(); i++ {
// v := sv.Index(i).Interface()
// mp[v] = true
//}
//
//var res []interface{}
//for k := range mp {
// res = append(res, mp[k])
//}
//return res
return res
}
// Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
func Union(slices ...interface{}) interface{} {
func Union[T comparable](slices ...[]T) []T {
if len(slices) == 0 {
return nil
return []T{}
}
// append all slices, then unique it
var allSlices []interface{}
len := 0
for i := range slices {
sv := sliceValue(slices[i])
len += sv.Len()
for j := 0; j < sv.Len(); j++ {
v := sv.Index(j).Interface()
allSlices = append(allSlices, v)
var allElements []T
for _, slice := range slices {
for _, v := range slice {
allElements = append(allElements, v)
}
}
sv := sliceValue(slices[0])
res := reflect.MakeSlice(sv.Type(), len, len)
for i := 0; i < len; i++ {
res.Index(i).Set(reflect.ValueOf(allSlices[i]))
}
return Unique(res.Interface())
return Unique(allElements)
}
// Intersection creates a slice of unique values that included by all slices.
func Intersection(slices ...interface{}) interface{} {
func Intersection[T comparable](slices ...[]T) []T {
var res []T
if len(slices) == 0 {
return nil
return []T{}
}
if len(slices) == 1 {
return Unique(slices[0])
}
reduceFunc := func(index int, slice1, slice2 interface{}) interface{} {
set := make([]interface{}, 0)
hash := make(map[interface{}]bool)
sv1 := reflect.ValueOf(slice1)
for i := 0; i < sv1.Len(); i++ {
v := sv1.Index(i).Interface()
hash[v] = true
}
sv2 := reflect.ValueOf(slice2)
for i := 0; i < sv2.Len(); i++ {
el := sv2.Index(i).Interface()
if _, found := hash[el]; found {
set = append(set, el)
//return elements both in slice1 and slice2
reduceFunc := func(slice1, slice2 []T) []T {
s := make([]T, 0, 0)
for _, v := range slice1 {
if Contain(slice2, v) {
s = append(s, v)
}
}
res := reflect.MakeSlice(sv1.Type(), len(set), len(set))
for i := 0; i < len(set); i++ {
res.Index(i).Set(reflect.ValueOf(set[i]))
}
return res.Interface()
return s
}
res = reduceFunc(slices[0], slices[1])
if len(slices) == 2 {
return Unique(res)
}
tmp := make([][]T, 2, 2)
for i := 2; i < len(slices); i++ {
tmp[0] = res
tmp[1] = slices[i]
res = reduceFunc(tmp[0], tmp[1])
}
res := Reduce(slices, reduceFunc, nil)
return Unique(res)
}

View File

@@ -8,79 +8,34 @@ import (
)
func TestContain(t *testing.T) {
t1 := []string{"a", "b", "c", "d"}
contain(t, t1, "a", true)
contain(t, t1, "e", false)
assert := internal.NewAssert(t, "TestContain")
var t2 []string
contain(t, t2, "1", false)
assert.Equal(true, Contain([]string{"a", "b", "c"}, "a"))
assert.Equal(false, Contain([]string{"a", "b", "c"}, "d"))
assert.Equal(true, Contain([]string{""}, ""))
assert.Equal(false, Contain([]string{}, ""))
m := make(map[string]int)
m["a"] = 1
contain(t, m, "a", true)
contain(t, m, "b", false)
s := "hello"
contain(t, s, "h", true)
contain(t, s, "s", false)
}
func contain(t *testing.T, test interface{}, value interface{}, expected bool) {
res := Contain(test, value)
if res != expected {
internal.LogFailedTestInfo(t, "Contain", test, expected, res)
t.FailNow()
}
assert.Equal(true, Contain([]int{1, 2, 3}, 1))
}
func TestChunk(t *testing.T) {
t1 := []string{"a", "b", "c", "d", "e"}
assert := internal.NewAssert(t, "TestChunk")
r1 := [][]interface{}{
{"a"},
{"b"},
{"c"},
{"d"},
{"e"},
}
chunk(t, InterfaceSlice(t1), 1, r1)
arr := []string{"a", "b", "c", "d", "e"}
r1 := [][]string{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
assert.Equal(r1, Chunk(arr, 1))
r2 := [][]interface{}{
{"a", "b"},
{"c", "d"},
{"e"},
}
chunk(t, InterfaceSlice(t1), 2, r2)
r2 := [][]string{{"a", "b"}, {"c", "d"}, {"e"}}
assert.Equal(r2, Chunk(arr, 2))
r3 := [][]interface{}{
{"a", "b", "c"},
{"d", "e"},
}
chunk(t, InterfaceSlice(t1), 3, r3)
r3 := [][]string{{"a", "b", "c"}, {"d", "e"}}
assert.Equal(r3, Chunk(arr, 3))
r4 := [][]interface{}{
{"a", "b", "c", "d"},
{"e"},
}
chunk(t, InterfaceSlice(t1), 4, r4)
r4 := [][]string{{"a", "b", "c", "d"}, {"e"}}
assert.Equal(r4, Chunk(arr, 4))
r5 := [][]interface{}{
{"a"},
{"b"},
{"c"},
{"d"},
{"e"},
}
chunk(t, InterfaceSlice(t1), 5, r5)
}
func chunk(t *testing.T, test []interface{}, num int, expected [][]interface{}) {
res := Chunk(test, num)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "Chunk", test, expected, res)
t.FailNow()
}
r5 := [][]string{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
assert.Equal(r5, Chunk(arr, 5))
}
func TestConvertSlice(t *testing.T) {
@@ -101,11 +56,9 @@ func TestEvery(t *testing.T) {
isEven := func(i, num int) bool {
return num%2 == 0
}
res := Every(nums, isEven)
if res != false {
internal.LogFailedTestInfo(t, "Every", nums, false, res)
t.FailNow()
}
assert := internal.NewAssert(t, "TestEvery")
assert.Equal(false, Every(nums, isEven))
}
func TestNone(t *testing.T) {
@@ -113,42 +66,34 @@ func TestNone(t *testing.T) {
check := func(i, num int) bool {
return num%2 == 1
}
res := None(nums, check)
if res != false {
internal.LogFailedTestInfo(t, "None", nums, false, res)
t.FailNow()
}
assert := internal.NewAssert(t, "TestNone")
assert.Equal(false, None(nums, check))
}
func TestSome(t *testing.T) {
nums := []int{1, 2, 3, 5}
isEven := func(i, num int) bool {
hasEven := func(i, num int) bool {
return num%2 == 0
}
res := Some(nums, isEven)
if res != true {
internal.LogFailedTestInfo(t, "Some", nums, true, res)
t.FailNow()
}
assert := internal.NewAssert(t, "TestSome")
assert.Equal(true, Some(nums, hasEven))
}
func TestFilter(t *testing.T) {
nums := []int{1, 2, 3, 4, 5}
even := func(i, num int) bool {
isEven := func(i, num int) bool {
return num%2 == 0
}
e1 := []int{2, 4}
r1 := Filter(nums, even)
if !reflect.DeepEqual(r1, e1) {
internal.LogFailedTestInfo(t, "Filter", nums, e1, r1)
t.FailNow()
}
assert := internal.NewAssert(t, "TestFilter")
assert.Equal([]int{2, 4}, Filter(nums, isEven))
type student struct {
name string
age int
}
students := []student{
{"a", 10},
{"b", 11},
@@ -156,8 +101,7 @@ func TestFilter(t *testing.T) {
{"d", 13},
{"e", 14},
}
e2 := []student{
studentsOfAageGreat12 := []student{
{"d", 13},
{"e", 14},
}
@@ -165,12 +109,7 @@ func TestFilter(t *testing.T) {
return s.age > 12
}
r2 := Filter(students, filterFunc)
if !reflect.DeepEqual(r2, e2) {
internal.LogFailedTestInfo(t, "Filter", students, e2, r2)
t.FailNow()
}
assert.Equal(studentsOfAageGreat12, Filter(students, filterFunc))
}
func TestGroupBy(t *testing.T) {
@@ -179,22 +118,12 @@ func TestGroupBy(t *testing.T) {
return (num % 2) == 0
}
expectedEven := []int{2, 4, 6}
expectedOdd := []int{1, 3, 5}
even, odd := GroupBy(nums, evenFunc)
t.Log("odd", odd)
t.Log("even", even)
if !reflect.DeepEqual(IntSlice(even), expectedEven) {
internal.LogFailedTestInfo(t, "GroupBy even", nums, expectedEven, even)
t.FailNow()
}
expectedOdd := []int{1, 3, 5}
if !reflect.DeepEqual(IntSlice(odd), expectedOdd) {
internal.LogFailedTestInfo(t, "GroupBy odd", nums, expectedOdd, odd)
t.FailNow()
}
assert := internal.NewAssert(t, "TestGroupBy")
assert.Equal(expectedEven, even)
assert.Equal(expectedOdd, odd)
}
func TestCount(t *testing.T) {
@@ -202,12 +131,9 @@ func TestCount(t *testing.T) {
evenFunc := func(i, num int) bool {
return (num % 2) == 0
}
c := Count(nums, evenFunc)
if c != 3 {
internal.LogFailedTestInfo(t, "Count", nums, 3, c)
t.FailNow()
}
assert := internal.NewAssert(t, "TestCount")
assert.Equal(3, Count(nums, evenFunc))
}
func TestFind(t *testing.T) {
@@ -220,10 +146,8 @@ func TestFind(t *testing.T) {
t.Fatal("found nothing")
}
if res != 2 {
internal.LogFailedTestInfo(t, "Find", nums, 2, res)
t.FailNow()
}
assert := internal.NewAssert(t, "TestFind")
assert.Equal(2, *res)
}
func TestFindFoundNothing(t *testing.T) {
@@ -232,20 +156,19 @@ func TestFindFoundNothing(t *testing.T) {
return num > 1
}
_, ok := Find(nums, findFunc)
if ok {
t.Fatal("found something")
}
// if ok {
// t.Fatal("found something")
// }
assert := internal.NewAssert(t, "TestFindFoundNothing")
assert.Equal(false, ok)
}
func TestFlattenDeep(t *testing.T) {
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
expected := []string{"a", "b", "c", "d"}
res := FlattenDeep(input)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "FlattenDeep", input, expected, res)
t.FailNow()
}
assert := internal.NewAssert(t, "TestFlattenDeep")
assert.Equal(expected, FlattenDeep(input))
}
func TestForEach(t *testing.T) {
@@ -259,26 +182,18 @@ func TestForEach(t *testing.T) {
ForEach(numbers, addTwo)
if !reflect.DeepEqual(numbersAddTwo, expected) {
internal.LogFailedTestInfo(t, "ForEach", numbers, expected, numbersAddTwo)
t.FailNow()
}
assert := internal.NewAssert(t, "TestForEach")
assert.Equal(expected, numbersAddTwo)
}
func TestMap(t *testing.T) {
numbers := []int{1, 2, 3, 4}
nums := []int{1, 2, 3, 4}
multiplyTwo := func(i, num int) int {
return num * 2
}
expected := []int{2, 4, 6, 8}
actual := Map(numbers, multiplyTwo)
if !reflect.DeepEqual(actual, expected) {
internal.LogFailedTestInfo(t, "Map", numbers, expected, actual)
t.FailNow()
}
assert := internal.NewAssert(t, "TestMap")
assert.Equal([]int{2, 4, 6, 8}, Map(nums, multiplyTwo))
type student struct {
name string
@@ -289,8 +204,7 @@ func TestMap(t *testing.T) {
{"b", 2},
{"c", 3},
}
e2 := []student{
studentsOfAdd10Aage := []student{
{"a", 11},
{"b", 12},
{"c", 13},
@@ -299,11 +213,8 @@ func TestMap(t *testing.T) {
s.age += 10
return s
}
r2 := Map(students, mapFunc)
if !reflect.DeepEqual(r2, e2) {
internal.LogFailedTestInfo(t, "Filter", students, e2, r2)
t.FailNow()
}
assert.Equal(studentsOfAdd10Aage, Map(students, mapFunc))
}
func TestReduce(t *testing.T) {
@@ -311,239 +222,154 @@ func TestReduce(t *testing.T) {
{},
{1},
{1, 2, 3, 4}}
expected := []int{0, 1, 10}
f := func(i, v1, v2 int) int {
return v1 + v2
}
assert := internal.NewAssert(t, "TestReduce")
for i := 0; i < len(cases); i++ {
res := Reduce(cases[i], f, 0)
if res != expected[i] {
internal.LogFailedTestInfo(t, "Reduce", cases[i], expected[i], res)
t.FailNow()
}
actual := Reduce(cases[i], f, 0)
assert.Equal(expected[i], actual)
}
}
func TestIntSlice(t *testing.T) {
var t1 []interface{}
t1 = append(t1, 1, 2, 3, 4, 5)
expect := []int{1, 2, 3, 4, 5}
intSlice(t, t1, expect)
}
var nums []interface{}
nums = append(nums, 1, 2, 3)
func intSlice(t *testing.T, test interface{}, expected []int) {
res := IntSlice(test)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "IntSlice", test, expected, res)
t.FailNow()
}
assert := internal.NewAssert(t, "TestIntSlice")
assert.Equal([]int{1, 2, 3}, IntSlice(nums))
}
func TestStringSlice(t *testing.T) {
var t1 []interface{}
t1 = append(t1, "a", "b", "c", "d", "e")
expect := []string{"a", "b", "c", "d", "e"}
stringSlice(t, t1, expect)
}
var strs []interface{}
strs = append(strs, "a", "b", "c")
func stringSlice(t *testing.T, test interface{}, expected []string) {
res := StringSlice(test)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "StringSlice", test, expected, res)
t.FailNow()
}
assert := internal.NewAssert(t, "TestStringSlice")
assert.Equal([]string{"a", "b", "c"}, StringSlice(strs))
}
func TestInterfaceSlice(t *testing.T) {
t1 := []string{"a", "b", "c", "d", "e"}
expect := []interface{}{"a", "b", "c", "d", "e"}
interfaceSlice(t, t1, expect)
}
strs := []string{"a", "b", "c"}
expect := []interface{}{"a", "b", "c"}
func interfaceSlice(t *testing.T, test interface{}, expected []interface{}) {
res := InterfaceSlice(test)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "InterfaceSlice", test, expected, res)
t.FailNow()
}
assert := internal.NewAssert(t, "TestInterfaceSlice")
assert.Equal(expect, InterfaceSlice(strs))
}
func TestDeleteByIndex(t *testing.T) {
origin := []string{"a", "b", "c", "d", "e"}
assert := internal.NewAssert(t, "TestDeleteByIndex")
t1 := []string{"a", "b", "c", "d", "e"}
r1 := []string{"b", "c", "d", "e"}
deleteByIndex(t, origin, t1, 0, 0, r1)
a1, _ := DeleteByIndex(t1, 0)
assert.Equal(r1, a1)
t1 = []string{"a", "b", "c", "d", "e"}
t2 := []string{"a", "b", "c", "d", "e"}
r2 := []string{"a", "b", "c", "e"}
deleteByIndex(t, origin, t1, 3, 0, r2)
a2, _ := DeleteByIndex(t2, 3)
assert.Equal(r2, a2)
t1 = []string{"a", "b", "c", "d", "e"}
r3 := []string{"a", "b", "c", "d"}
deleteByIndex(t, origin, t1, 4, 0, r3)
t3 := []string{"a", "b", "c", "d", "e"}
r3 := []string{"c", "d", "e"}
a3, _ := DeleteByIndex(t3, 0, 2)
assert.Equal(r3, a3)
t1 = []string{"a", "b", "c", "d", "e"}
r4 := []string{"c", "d", "e"}
deleteByIndex(t, origin, t1, 0, 2, r4)
t4 := []string{"a", "b", "c", "d", "e"}
r4 := []string{}
a4, _ := DeleteByIndex(t4, 0, 5)
assert.Equal(r4, a4)
t1 = []string{"a", "b", "c", "d", "e"}
r5 := []string{} // var r5 []string{} failed
deleteByIndex(t, origin, t1, 0, 5, r5)
t5 := []string{"a", "b", "c", "d", "e"}
_, err := DeleteByIndex(t5, 1, 1)
assert.IsNotNil(err)
// failed
//t1 = []string{"a", "b", "c", "d","e"}
//r6 := []string{"a", "c", "d","e"}
//deleteByIndex(t, origin, t1, 1, 1, r6)
// failed
//t1 = []string{"a", "b", "c", "d","e"}
//r7 := []string{}
//deleteByIndex(t, origin, t1, 0, 6, r7)
}
func deleteByIndex(t *testing.T, origin, test interface{}, start, end int, expected interface{}) {
var res interface{}
var err error
if end != 0 {
res, err = DeleteByIndex(test, start, end)
} else {
res, err = DeleteByIndex(test, start)
}
if err != nil {
t.Error("DeleteByIndex Error: " + err.Error())
}
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "DeleteByIndex", origin, expected, res)
t.FailNow()
}
_, err = DeleteByIndex(t5, 0, 6)
assert.IsNotNil(err)
}
func TestDrop(t *testing.T) {
drop(t, []int{}, 0, []int{})
drop(t, []int{}, 1, []int{})
drop(t, []int{}, -1, []int{})
assert := internal.NewAssert(t, "TestInterfaceSlice")
drop(t, []int{1, 2, 3, 4, 5}, 0, []int{1, 2, 3, 4, 5})
drop(t, []int{1, 2, 3, 4, 5}, 1, []int{2, 3, 4, 5})
drop(t, []int{1, 2, 3, 4, 5}, 5, []int{})
drop(t, []int{1, 2, 3, 4, 5}, 6, []int{})
assert.Equal([]int{}, Drop([]int{}, 0))
assert.Equal([]int{}, Drop([]int{}, 1))
assert.Equal([]int{}, Drop([]int{}, -1))
drop(t, []int{1, 2, 3, 4, 5}, -1, []int{1, 2, 3, 4})
drop(t, []int{1, 2, 3, 4, 5}, -5, []int{})
drop(t, []int{1, 2, 3, 4, 5}, -6, []int{})
}
assert.Equal([]int{1, 2, 3, 4, 5}, Drop([]int{1, 2, 3, 4, 5}, 0))
assert.Equal([]int{2, 3, 4, 5}, Drop([]int{1, 2, 3, 4, 5}, 1))
assert.Equal([]int{}, Drop([]int{1, 2, 3, 4, 5}, 5))
assert.Equal([]int{}, Drop([]int{1, 2, 3, 4, 5}, 6))
func drop(t *testing.T, test interface{}, n int, expected interface{}) {
res := Drop(test, n)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "Drop", test, expected, res)
t.FailNow()
}
assert.Equal([]int{1, 2, 3, 4}, Drop([]int{1, 2, 3, 4, 5}, -1))
assert.Equal([]int{}, Drop([]int{1, 2, 3, 4, 5}, -6))
assert.Equal([]int{}, Drop([]int{1, 2, 3, 4, 5}, -6))
}
func TestInsertByIndex(t *testing.T) {
assert := internal.NewAssert(t, "TestInsertByIndex")
t1 := []string{"a", "b", "c"}
r1, _ := InsertByIndex(t1, 0, "1")
assert.Equal([]string{"1", "a", "b", "c"}, r1)
r1 := []string{"1", "a", "b", "c"}
insertByIndex(t, t1, 0, "1", r1)
r2, _ := InsertByIndex(t1, 1, "1")
assert.Equal([]string{"a", "1", "b", "c"}, r2)
r2 := []string{"a", "1", "b", "c"}
insertByIndex(t, t1, 1, "1", r2)
r3, _ := InsertByIndex(t1, 3, "1")
assert.Equal([]string{"a", "b", "c", "1"}, r3)
r3 := []string{"a", "b", "c", "1"}
insertByIndex(t, t1, 3, "1", r3)
r4, _ := InsertByIndex(t1, 0, []string{"1", "2", "3"})
assert.Equal([]string{"1", "2", "3", "a", "b", "c"}, r4)
r4 := []string{"1", "2", "3", "a", "b", "c"}
insertByIndex(t, t1, 0, []string{"1", "2", "3"}, r4)
r5, _ := InsertByIndex(t1, 3, []string{"1", "2", "3"})
assert.Equal([]string{"a", "b", "c", "1", "2", "3"}, r5)
r5 := []string{"a", "1", "2", "3", "b", "c"}
insertByIndex(t, t1, 1, []string{"1", "2", "3"}, r5)
_, err := InsertByIndex(t1, 4, "1")
assert.IsNotNil(err)
r6 := []string{"a", "b", "1", "2", "3", "c"}
insertByIndex(t, t1, 2, []string{"1", "2", "3"}, r6)
r7 := []string{"a", "b", "c", "1", "2", "3"}
insertByIndex(t, t1, 3, []string{"1", "2", "3"}, r7)
}
func insertByIndex(t *testing.T, test interface{}, index int, value, expected interface{}) {
res, err := InsertByIndex(test, index, value)
if err != nil {
t.Error("InsertByIndex Error: " + err.Error())
}
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "InsertByIndex", test, expected, res)
t.FailNow()
}
_, err = InsertByIndex(t1, 0, 1)
assert.IsNotNil(err)
}
func TestUpdateByIndex(t *testing.T) {
assert := internal.NewAssert(t, "TestUpdateByIndex")
t1 := []string{"a", "b", "c"}
r1 := []string{"1", "b", "c"}
updateByIndex(t, t1, 0, "1", r1)
r1, _ := UpdateByIndex(t1, 0, "1")
assert.Equal([]string{"1", "b", "c"}, r1)
t1 = []string{"a", "b", "c"}
r2 := []string{"a", "1", "c"}
updateByIndex(t, t1, 1, "1", r2)
t2 := []string{"a", "b", "c"}
r2, _ := UpdateByIndex(t2, 1, "1")
assert.Equal([]string{"a", "1", "c"}, r2)
t1 = []string{"a", "b", "c"}
r3 := []string{"a", "b", "1"}
updateByIndex(t, t1, 2, "1", r3)
_, err := UpdateByIndex([]string{"a", "b", "c"}, 4, "1")
assert.IsNotNil(err)
}
func updateByIndex(t *testing.T, test interface{}, index int, value, expected interface{}) {
res, err := UpdateByIndex(test, index, value)
if err != nil {
t.Error("UpdateByIndex Error: " + err.Error())
}
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "UpdateByIndex", test, expected, res)
t.FailNow()
}
_, err = UpdateByIndex([]string{"a", "b", "c"}, 0, 1)
assert.IsNotNil(err)
}
func TestUnique(t *testing.T) {
t1 := []int{1, 2, 2, 3}
e1 := []int{1, 2, 3}
r1 := Unique(t1)
if !reflect.DeepEqual(r1, e1) {
internal.LogFailedTestInfo(t, "Unique", t1, e1, r1)
t.FailNow()
}
assert := internal.NewAssert(t, "TestUnique")
t2 := []string{"a", "a", "b", "c"}
e2 := []string{"a", "b", "c"}
r2 := Unique(t2)
if !reflect.DeepEqual(r2, e2) {
internal.LogFailedTestInfo(t, "Unique", t2, e2, r2)
t.FailNow()
}
assert.Equal([]int{1, 2, 3}, Unique([]int{1, 2, 2, 3}))
assert.Equal([]string{"a", "b", "c"}, Unique([]string{"a", "a", "b", "c"}))
}
func TestUnion(t *testing.T) {
assert := internal.NewAssert(t, "TestUnion")
s1 := []int{1, 3, 4, 6}
s2 := []int{1, 2, 5, 6}
s3 := []int{0, 4, 5, 7}
expected1 := []int{1, 3, 4, 6, 2, 5, 0, 7}
res1 := Union(s1, s2, s3)
if !reflect.DeepEqual(res1, expected1) {
internal.LogFailedTestInfo(t, "Union", s1, expected1, res1)
t.FailNow()
}
expected2 := []int{1, 3, 4, 6}
res2 := Union(s1)
if !reflect.DeepEqual(res2, expected2) {
internal.LogFailedTestInfo(t, "Union", s1, expected2, res2)
t.FailNow()
}
assert.Equal([]int{1, 3, 4, 6, 2, 5, 0, 7}, Union(s1, s2, s3))
assert.Equal([]int{1, 3, 4, 6, 2, 5}, Union(s1, s2))
assert.Equal([]int{1, 3, 4, 6}, Union(s1))
}
func TestIntersection(t *testing.T) {
@@ -564,45 +390,37 @@ func TestIntersection(t *testing.T) {
Intersection(s1),
Intersection(s1, s4),
}
for i := 0; i < len(res); i++ {
if !reflect.DeepEqual(res[i], expected[i]) {
internal.LogFailedTestInfo(t, "Intersection", "Intersection", expected[i], res[i])
t.FailNow()
}
}
assert := internal.NewAssert(t, "TestIntersection")
for i := 0; i < len(res); i++ {
assert.Equal(expected[i], res[i])
}
}
func TestReverseSlice(t *testing.T) {
assert := internal.NewAssert(t, "TestIntersection")
s1 := []int{1, 2, 3, 4, 5}
e1 := []int{5, 4, 3, 2, 1}
ReverseSlice(s1)
if !reflect.DeepEqual(s1, e1) {
internal.LogFailedTestInfo(t, "ReverseSlice", s1, e1, s1)
t.FailNow()
}
assert.Equal([]int{5, 4, 3, 2, 1}, s1)
s2 := []string{"a", "b", "c", "d", "e"}
e2 := []string{"e", "d", "c", "b", "a"}
ReverseSlice(s2)
if !reflect.DeepEqual(s2, e2) {
internal.LogFailedTestInfo(t, "ReverseSlice", s2, e2, s2)
t.FailNow()
}
assert.Equal([]string{"e", "d", "c", "b", "a"}, s2)
}
func TestDifference(t *testing.T) {
assert := internal.NewAssert(t, "TestIntersection")
s1 := []int{1, 2, 3, 4, 5}
s2 := []int{4, 5, 6}
e1 := []int{1, 2, 3}
r1 := Difference(s1, s2)
if !reflect.DeepEqual(r1, e1) {
internal.LogFailedTestInfo(t, "Difference", s1, e1, r1)
t.FailNow()
}
assert.Equal([]int{1, 2, 3}, Difference(s1, s2))
}
func TestSortByField(t *testing.T) {
assert := internal.NewAssert(t, "TestWithout")
type student struct {
name string
age int
@@ -613,8 +431,7 @@ func TestSortByField(t *testing.T) {
{"c", 5},
{"d", 6},
}
sortByAge := []student{
studentsOfSortByAge := []student{
{"b", 15},
{"a", 10},
{"d", 6},
@@ -622,35 +439,35 @@ func TestSortByField(t *testing.T) {
}
err := SortByField(students, "age", "desc")
if err != nil {
t.Error("IntSlice Error: " + err.Error())
}
if !reflect.DeepEqual(students, sortByAge) {
internal.LogFailedTestInfo(t, "SortByField", students, sortByAge, students)
t.FailNow()
}
assert.IsNil(err)
assert.Equal(students, studentsOfSortByAge)
}
func TestWithout(t *testing.T) {
s := []int{1, 2, 3, 4, 5}
expected := []int{3, 4, 5}
res := Without(s, 1, 2)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "Without", s, expected, res)
t.FailNow()
}
assert := internal.NewAssert(t, "TestWithout")
assert.Equal([]int{3, 4, 5}, Without([]int{1, 2, 3, 4, 5}, 1, 2))
assert.Equal([]int{1, 2, 3, 4, 5}, Without([]int{1, 2, 3, 4, 5}))
}
func TestShuffle(t *testing.T) {
assert := internal.NewAssert(t, "TestShuffle")
s := []int{1, 2, 3, 4, 5}
res := Shuffle(s)
t.Log("Shuffle result: ", res)
if reflect.TypeOf(s) != reflect.TypeOf(res) {
internal.LogFailedTestInfo(t, "Shuffle", s, res, res)
t.FailNow()
}
assert.Equal(reflect.TypeOf(s), reflect.TypeOf(res))
rv := reflect.ValueOf(res)
assert.Equal(5, rv.Len())
assert.Equal(true, rv.Kind() == reflect.Slice)
assert.Equal(true, rv.Type().Elem().Kind() == reflect.Int)
// assert.Equal(true, Contain(res, 1))
// assert.Equal(true, Contain(res, 2))
// assert.Equal(true, Contain(res, 3))
// assert.Equal(true, Contain(res, 4))
// assert.Equal(true, Contain(res, 5))
}