Skip to content

Commit

Permalink
Merge pull request #10 from lxzan/dev
Browse files Browse the repository at this point in the history
add groupBy
  • Loading branch information
lxzan committed Jan 11, 2024
2 parents 27d4f4c + 8a0206f commit f769d89
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 6 deletions.
32 changes: 32 additions & 0 deletions algo/algorithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package algo

import (
"github.com/lxzan/dao/types/cmp"
"reflect"
"strconv"
)

Expand Down Expand Up @@ -105,6 +106,14 @@ func SelectValue[T any](flag bool, a T, b T) T {
return b
}

// WithDefault 如果原值为零值, 返回新值, 否则返回原值
func WithDefault[T comparable](rawValue, newValue T) T {
if IsZero(rawValue) {
return newValue
}
return rawValue
}

// Contains 是否包含
func Contains[T comparable](arr []T, target T) bool {
for i := range arr {
Expand Down Expand Up @@ -140,3 +149,26 @@ func IsZero[T comparable](v T) bool {
var zero T
return v == zero
}

// IsNil 判断空指针
func IsNil(v any) bool {
if v == nil {
return true
}
return reflect.ValueOf(v).IsNil()
}

// NotNil 判断不为空
func NotNil(v any) bool {
return !IsNil(v)
}

// GroupBy 分组
func GroupBy[T any, A ~[]T, K cmp.Ordered](arr A, transfer func(i int, v T) K) map[K]A {
var m = make(map[K]A, len(arr))
for index, value := range arr {
key := transfer(index, value)
m[key] = append(m[key], value)
}
return m
}
44 changes: 44 additions & 0 deletions algo/algorithm_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package algo

import (
"errors"
"github.com/lxzan/dao/hashmap"
"github.com/lxzan/dao/internal/utils"
"github.com/stretchr/testify/assert"
"math/rand"
"net"
"net/http"
"testing"
)
Expand Down Expand Up @@ -209,3 +211,45 @@ func TestSum(t *testing.T) {
assert.Equal(t, Sum([]int{1, 3, 5, 7, 9}), 25)
assert.Equal(t, Sum([]uint32{1, 3, 5, 7, 9}), uint32(25))
}

func TestGroupBy(t *testing.T) {
t.Run("", func(t *testing.T) {
var arr = []int{1, 3, 5, 7, 2, 4, 6, 8}
var m = GroupBy(arr, func(i int, v int) int {
return v % 2
})
assert.ElementsMatch(t, m[0], []int{2, 4, 6, 8})
assert.ElementsMatch(t, m[1], []int{1, 3, 5, 7})
})

t.Run("", func(t *testing.T) {
var arr = []int{1, 3, 5, 7, 2, 4, 6, 8}
var m = GroupBy(arr, func(i int, v int) int {
return v % 3
})
assert.ElementsMatch(t, m[0], []int{3, 6})
assert.ElementsMatch(t, m[1], []int{1, 4, 7})
assert.ElementsMatch(t, m[2], []int{2, 5, 8})
})
}

func TestIsNil(t *testing.T) {
var conn1 *net.TCPConn
var conn2 net.Conn = conn1
var conn3 = &net.TCPConn{}
assert.True(t, IsNil(conn1))
assert.True(t, IsNil(conn2))
assert.False(t, IsNil(conn3))
}

func TestNotNil(t *testing.T) {
assert.True(t, NotNil(errors.New("1")))
assert.False(t, NotNil(nil))
}

func TestWithDefault(t *testing.T) {
assert.Equal(t, WithDefault(0, 1), 1)
assert.Equal(t, WithDefault(2, 1), 2)
assert.Equal(t, WithDefault("", "1"), "1")
assert.Equal(t, WithDefault("2", "1"), "2")
}
30 changes: 25 additions & 5 deletions vector/vector.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package vector

import (
"github.com/lxzan/dao/algo"
"github.com/lxzan/dao/hashmap"
"github.com/lxzan/dao/internal/utils"
"github.com/lxzan/dao/types/cmp"
"unsafe"
Expand All @@ -24,6 +23,9 @@ func (c *Vector[K, V]) Reset() {

// Len 获取元素数量
func (c *Vector[K, V]) Len() int {
if c == nil {
return 0
}
return len(*c)
}

Expand Down Expand Up @@ -99,21 +101,39 @@ func (c *Vector[K, V]) Unique() *Vector[K, V] {
return c
}

// UniqueByString 通过string类型字段去重
func (c *Vector[K, V]) UniqueByString(transfer func(v V) string) *Vector[K, V] {
*c = algo.UniqueBy(*c, transfer)
return c
}

// UniqueByInt 通过int类型字段去重
func (c *Vector[K, V]) UniqueByInt(transfer func(v V) int) *Vector[K, V] {
*c = algo.UniqueBy(*c, transfer)
return c
}

// UniqueByInt64 通过int64类型字段去重
func (c *Vector[K, V]) UniqueByInt64(transfer func(v V) int64) *Vector[K, V] {
*c = algo.UniqueBy(*c, transfer)
return c
}

// GroupByString 通过string类型字段分组
func (c *Vector[K, V]) GroupByString(transfer func(i int, v V) string) map[string][]V {
return algo.GroupBy(c.Elem(), transfer)
}

// GroupByInt 通过int类型字段分组
func (c *Vector[K, V]) GroupByInt(transfer func(i int, v V) int) map[int][]V {
return algo.GroupBy(c.Elem(), transfer)
}

// GroupByInt64 通过int64类型字段分组
func (c *Vector[K, V]) GroupByInt64(transfer func(i int, v V) int64) map[int64][]V {
return algo.GroupBy(c.Elem(), transfer)
}

// Filter 过滤
func (c *Vector[K, V]) Filter(f func(i int, v V) bool) *Vector[K, V] {
*c = algo.Filter(*c, f)
Expand Down Expand Up @@ -144,11 +164,11 @@ func (c *Vector[K, V]) GetIdList() []K {
}
}

// ToMap 生成hashmap.HashMap[K, V]
func (c *Vector[K, V]) ToMap() hashmap.HashMap[K, V] {
var m = hashmap.New[K, V](c.Len())
// ToMap 转换为map
func (c *Vector[K, V]) ToMap() map[K]V {
var m = make(map[K]V, c.Len())
for _, item := range *c {
m.Set(item.GetID(), item)
m[item.GetID()] = item
}
return m
}
Expand Down
66 changes: 65 additions & 1 deletion vector/vector_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package vector

import (
"github.com/lxzan/dao/hashmap"
"github.com/lxzan/dao/internal/utils"
"github.com/stretchr/testify/assert"
"testing"
Expand Down Expand Up @@ -147,7 +148,7 @@ func TestVector_ToMap(t *testing.T) {
user{ID: "b"},
user{ID: "c"},
)
var values = a.ToMap().Keys()
var values = hashmap.HashMap[string, user](a.ToMap()).Keys()
assert.ElementsMatch(t, values, []string{"a", "b", "c"})
}

Expand Down Expand Up @@ -260,3 +261,66 @@ func TestVector_Get(t *testing.T) {
assert.Equal(t, v.Front(), Int(1))
assert.Equal(t, v.Back(), Int(5))
}

func TestVector_GroupByInt(t *testing.T) {
t.Run("", func(t *testing.T) {
var arr = NewFromInts(1, 3, 5, 7, 2, 4, 6, 8)
var m = arr.GroupByInt(func(i int, v Int) int {
return v.GetID() % 2
})
assert.ElementsMatch(t, m[0], Vector[int, Int]{2, 4, 6, 8})
assert.ElementsMatch(t, m[1], Vector[int, Int]{1, 3, 5, 7})
})

t.Run("", func(t *testing.T) {
var arr = NewFromInts(1, 3, 5, 7, 2, 4, 6, 8)
var m = arr.GroupByInt(func(i int, v Int) int {
return v.GetID() % 3
})
assert.ElementsMatch(t, m[0], Vector[int, Int]{3, 6})
assert.ElementsMatch(t, m[1], Vector[int, Int]{1, 4, 7})
assert.ElementsMatch(t, m[2], Vector[int, Int]{2, 5, 8})
})
}

func TestVector_GroupByInt64(t *testing.T) {
t.Run("", func(t *testing.T) {
var arr = NewFromInt64s(1, 3, 5, 7, 2, 4, 6, 8)
var m = arr.GroupByInt64(func(i int, v Int64) int64 {
return v.GetID() % 2
})
assert.ElementsMatch(t, m[0], Vector[int64, Int64]{2, 4, 6, 8})
assert.ElementsMatch(t, m[1], Vector[int64, Int64]{1, 3, 5, 7})
})

t.Run("", func(t *testing.T) {
var arr = NewFromInt64s(1, 3, 5, 7, 2, 4, 6, 8)
var m = arr.GroupByInt64(func(i int, v Int64) int64 {
return v.GetID() % 3
})
assert.ElementsMatch(t, m[0], Vector[int64, Int64]{3, 6})
assert.ElementsMatch(t, m[1], Vector[int64, Int64]{1, 4, 7})
assert.ElementsMatch(t, m[2], Vector[int64, Int64]{2, 5, 8})
})
}

func TestVector_GroupByString(t *testing.T) {
var arr = NewFromStrings("abc", "abnormal", "oh", "oho", "bank", "bark")
var m = arr.GroupByString(func(i int, v String) string {
return v.GetID()[:2]
})
assert.ElementsMatch(t, m["ab"], Vector[string, String]{"abc", "abnormal"})
assert.ElementsMatch(t, m["oh"], Vector[string, String]{"oh", "oho"})
assert.ElementsMatch(t, m["ba"], Vector[string, String]{"bank", "bark"})
}

func TestVector_Cap(t *testing.T) {
var arr = make([]Int, 0, 3)
var v = Vector[int, Int](arr)
assert.Equal(t, v.Cap(), 3)
}

func TestVector_Len(t *testing.T) {
var v *Vector[string, String]
assert.Equal(t, v.Len(), 0)
}

0 comments on commit f769d89

Please sign in to comment.