mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-17 03:02:28 +08:00
feat: add Intersection, Union, Without func for slice/slice.go
This commit is contained in:
104
slice/slice.go
104
slice/slice.go
@@ -379,22 +379,28 @@ func Unique(slice interface{}) interface{} {
|
|||||||
return slice
|
return slice
|
||||||
}
|
}
|
||||||
|
|
||||||
var res []interface{}
|
var temp []interface{}
|
||||||
|
len := 0
|
||||||
for i := 0; i < sv.Len(); i++ {
|
for i := 0; i < sv.Len(); i++ {
|
||||||
v := sv.Index(i).Interface()
|
v := sv.Index(i).Interface()
|
||||||
flag := true
|
skip := true
|
||||||
for j := range res {
|
for j := range temp {
|
||||||
if v == res[j] {
|
if v == temp[j] {
|
||||||
flag = false
|
skip = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if flag {
|
if skip {
|
||||||
res = append(res, v)
|
temp = append(temp, v)
|
||||||
|
len++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
res := reflect.MakeSlice(sv.Type(), len, len)
|
||||||
|
for i := 0; i < len; 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
|
// if use map filter, the result slice element order is random, not same as origin slice
|
||||||
//mp := make(map[interface{}]bool)
|
//mp := make(map[interface{}]bool)
|
||||||
@@ -411,6 +417,66 @@ func Unique(slice interface{}) interface{} {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Union creates an slice of unique values, in order, from all given slices. using == for equality comparisons.
|
||||||
|
func Union(slices ...interface{}) interface{} {
|
||||||
|
if len(slices) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// append all slices, then unique it
|
||||||
|
var allSlice []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()
|
||||||
|
allSlice = append(allSlice, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sv := sliceValue(slices[0])
|
||||||
|
res := reflect.MakeSlice(sv.Type(), len, len)
|
||||||
|
for i := 0; i < len; i++ {
|
||||||
|
res.Index(i).Set(reflect.ValueOf(allSlice[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Unique(res.Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection creates an slice of unique values that included by all slices.
|
||||||
|
func Intersection(slices ...interface{}) interface{} {
|
||||||
|
if len(slices) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
res := Reduce(slices, reduceFunc, nil)
|
||||||
|
return Union(res)
|
||||||
|
}
|
||||||
|
|
||||||
// ReverseSlice return slice of element order is reversed to the given slice
|
// ReverseSlice return slice of element order is reversed to the given slice
|
||||||
func ReverseSlice(slice interface{}) {
|
func ReverseSlice(slice interface{}) {
|
||||||
v := sliceValue(slice)
|
v := sliceValue(slice)
|
||||||
@@ -474,3 +540,25 @@ func SortByField(slice interface{}, field string, sortType ...string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Without creates an array excluding all given values
|
||||||
|
func Without(slice interface{}, values ...interface{}) interface{} {
|
||||||
|
sv := sliceValue(slice)
|
||||||
|
if sv.Len() == 0 {
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
var indexes []int
|
||||||
|
for i := 0; i < sv.Len(); i++ {
|
||||||
|
v := sv.Index(i).Interface()
|
||||||
|
if !Contain(values, v) {
|
||||||
|
indexes = append(indexes, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res := reflect.MakeSlice(sv.Type(), len(indexes), len(indexes))
|
||||||
|
for i := range indexes {
|
||||||
|
res.Index(i).Set(sv.Index(indexes[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.Interface()
|
||||||
|
}
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ func updateByIndex(t *testing.T, test interface{}, index int, value, expected in
|
|||||||
func TestUnique(t *testing.T) {
|
func TestUnique(t *testing.T) {
|
||||||
t1 := []int{1, 2, 2, 3}
|
t1 := []int{1, 2, 2, 3}
|
||||||
e1 := []int{1, 2, 3}
|
e1 := []int{1, 2, 3}
|
||||||
r1, _ := IntSlice(Unique(t1))
|
r1 := Unique(t1)
|
||||||
if !reflect.DeepEqual(r1, e1) {
|
if !reflect.DeepEqual(r1, e1) {
|
||||||
utils.LogFailedTestInfo(t, "Unique", t1, e1, r1)
|
utils.LogFailedTestInfo(t, "Unique", t1, e1, r1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
@@ -403,13 +403,60 @@ func TestUnique(t *testing.T) {
|
|||||||
|
|
||||||
t2 := []string{"a", "a", "b", "c"}
|
t2 := []string{"a", "a", "b", "c"}
|
||||||
e2 := []string{"a", "b", "c"}
|
e2 := []string{"a", "b", "c"}
|
||||||
r2 := StringSlice(Unique(t2))
|
r2 := Unique(t2)
|
||||||
if !reflect.DeepEqual(r2, e2) {
|
if !reflect.DeepEqual(r2, e2) {
|
||||||
utils.LogFailedTestInfo(t, "Unique", t2, e2, r2)
|
utils.LogFailedTestInfo(t, "Unique", t2, e2, r2)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnion(t *testing.T) {
|
||||||
|
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) {
|
||||||
|
utils.LogFailedTestInfo(t, "Union", s1, expected1, res1)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
expected2 := []int{1, 3, 4, 6}
|
||||||
|
res2 := Union(s1)
|
||||||
|
if !reflect.DeepEqual(res2, expected2) {
|
||||||
|
utils.LogFailedTestInfo(t, "Union", s1, expected2, res2)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntersection(t *testing.T) {
|
||||||
|
s1 := []int{1, 2, 2, 3}
|
||||||
|
s2 := []int{1, 2, 3, 4}
|
||||||
|
s3 := []int{0, 2, 3, 5, 6}
|
||||||
|
s4 := []int{0, 5, 6}
|
||||||
|
|
||||||
|
expected := [][]int{
|
||||||
|
{2, 3},
|
||||||
|
{1, 2, 3},
|
||||||
|
{1, 2, 3},
|
||||||
|
{},
|
||||||
|
}
|
||||||
|
res := []interface{}{
|
||||||
|
Intersection(s1, s2, s3),
|
||||||
|
Intersection(s1, s2),
|
||||||
|
Intersection(s1),
|
||||||
|
Intersection(s1, s4),
|
||||||
|
}
|
||||||
|
for i := 0; i < len(res); i++ {
|
||||||
|
if !reflect.DeepEqual(res[i], expected[i]) {
|
||||||
|
utils.LogFailedTestInfo(t, "Intersection", "Intersection", expected[i], res[i])
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestReverseSlice(t *testing.T) {
|
func TestReverseSlice(t *testing.T) {
|
||||||
s1 := []int{1, 2, 3, 4, 5}
|
s1 := []int{1, 2, 3, 4, 5}
|
||||||
e1 := []int{5, 4, 3, 2, 1}
|
e1 := []int{5, 4, 3, 2, 1}
|
||||||
@@ -469,3 +516,14 @@ func TestSortByField(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
utils.LogFailedTestInfo(t, "Without", s, expected, res)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user