diff --git a/README.md b/README.md index 02332e6d..7d9a3d03 100644 --- a/README.md +++ b/README.md @@ -901,10 +901,15 @@ import "github.com/duke-git/lancet/v2/maputil" - **HasKey** : checks if map has key or not. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#HasKey)] [[play](https://go.dev/play/p/isZZHOsDhFc)] +- **MapToStruct** : converts map to struct. + [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#MapToStruct)] + [[play](https://go.dev/play/p/7wYyVfX38Dp)] - **ToSortedSlicesDefault** : converts a map to two slices sorted by key: one for the keys and another for the values. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ToSortedSlicesDefault)] + [[play](https://go.dev/play/p/43gEM2po-qy)] - **ToSortedSlicesWithComparator** : converts a map to two slices sorted by key and using a custom comparison function: one for the keys and another for the values. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ToSortedSlicesWithComparator)] + [[play](https://go.dev/play/p/0nlPo6YLdt3)] - **NewConcurrentMap** : creates a ConcurrentMap with specific shard count. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#NewConcurrentMap)] [[play](https://go.dev/play/p/3PenTPETJT0)] @@ -1440,9 +1445,10 @@ import "github.com/duke-git/lancet/v2/slice" [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Break)] - **RightPadding** : adds padding to the right end of a slice. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#RightPadding)] + [[play](https://go.dev/play/p/0_2rlLEMBXL)] - **LeftPadding** : adds padding to the left begin of a slice. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#LeftPadding)] - + [[play](https://go.dev/play/p/jlQVoelLl2k)]

19. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited.        index

diff --git a/README_zh-CN.md b/README_zh-CN.md index 384c8977..1bd7f9c4 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -903,10 +903,15 @@ import "github.com/duke-git/lancet/v2/maputil" - **HasKey** : 检查 map 是否包含某个 key。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#HasKey)] [[play](https://go.dev/play/p/isZZHOsDhFc)] +- **MapToStruct** : 将map转成struct。 + [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#MapToStruct)] + [[play](https://go.dev/play/p/7wYyVfX38Dp)] - **ToSortedSlicesDefault** : 将map的key和value转化成两个根据key的值从小到大排序的切片,value切片中元素的位置与key对应。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#ToSortedSlicesDefault)] + [[play](https://go.dev/play/p/43gEM2po-qy)] - **ToSortedSlicesWithComparator** : 将map的key和value转化成两个使用比较器函数根据key的值自定义排序规则的切片,value切片中元素的位置与key对应。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#ToSortedSlicesWithComparator)] + [[play](https://go.dev/play/p/0nlPo6YLdt3)] - **NewConcurrentMap** : ConcurrentMap 协程安全的 map 结构。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#NewConcurrentMap)] [[play](https://go.dev/play/p/3PenTPETJT0)] @@ -1439,8 +1444,11 @@ import "github.com/duke-git/lancet/v2/slice" [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Break)] - **RightPadding** : 在切片的右部添加元素。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#RightPadding)] + [[play](https://go.dev/play/p/0_2rlLEMBXL)] - **LeftPadding** : 在切片的左部添加元素。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#LeftPadding)] + [[play](https://go.dev/play/p/jlQVoelLl2k)] +

19. stream 流,该包仅验证简单的 stream 实现,功能有限。       回到目录

diff --git a/docs/api/packages/maputil.md b/docs/api/packages/maputil.md index 663f7612..14da11e7 100644 --- a/docs/api/packages/maputil.md +++ b/docs/api/packages/maputil.md @@ -948,14 +948,6 @@ func main() {

检查map是否包含某个key。用于代替以下样板代码:

-```go -_, haskey := amap["baz"]; - -if haskey { - fmt.Println("map has key baz") -} -``` - 函数签名: ```go @@ -990,6 +982,49 @@ func main() { } ``` +### MapToStruct + +

将map转成struct。

+ +函数签名: + +```go +func MapToStruct(m map[string]any, structObj any) error +``` + +示例:[运行](https://go.dev/play/p/7wYyVfX38Dp) + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/maputil" +) + +func main() { + personReqMap := map[string]any{ + "name": "Nothin", + "max_age": 35, + "page": 1, + "pageSize": 10, + } + + type PersonReq struct { + Name string `json:"name"` + MaxAge int `json:"max_age"` + Page int `json:"page"` + PageSize int `json:"pageSize"` + } + var personReq PersonReq + _ = maputil.MapToStruct(personReqMap, &personReq) + fmt.Println(personReq) + + // Output: + // {Nothin 35 1 10} +} +``` + ### ToSortedSlicesDefault

将map的key和value转化成两个根据key的值从小到大排序的切片,value切片中元素的位置与key对应。

@@ -1000,7 +1035,7 @@ func main() { func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V) ``` -示例:[运行](todo) +示例:[运行](https://go.dev/play/p/43gEM2po-qy) ```go package main @@ -1012,19 +1047,19 @@ import ( func main() { m := map[int]string{ - 1: "a", - 3: "c", - 2: "b", - } + 1: "a", + 3: "c", + 2: "b", + } - keys, values := ToSortedSlicesDefault(m) + keys, values := ToSortedSlicesDefault(m) - fmt.Println(keys) - fmt.Println(values) + fmt.Println(keys) + fmt.Println(values) - // Output: - // [1 2 3] - // [a b c] + // Output: + // [1 2 3] + // [a b c] } ``` @@ -1038,7 +1073,7 @@ func main() { func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V) ``` -示例:[运行](todo) +示例:[运行](https://go.dev/play/p/0nlPo6YLdt3) ```go package main @@ -1050,35 +1085,35 @@ import ( func main() { m1 := map[time.Time]string{ - time.Date(2024, 3, 31, 0, 0, 0, 0, time.UTC): "today", - time.Date(2024, 3, 30, 0, 0, 0, 0, time.UTC): "yesterday", - time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC): "tomorrow", - } - - keys1, values1 := ToSortedSlicesWithComparator(m1, func(a, b time.Time) bool { - return a.Before(b) - }) - - m2 := map[int]string{ - 1: "a", - 3: "c", - 2: "b", - } - keys2, values2 := ToSortedSlicesWithComparator(m2, func(a, b int) bool { - return a > b - }) - - fmt.Println(keys2) - fmt.Println(values2) - - fmt.Println(keys1) - fmt.Println(values1) - - // Output: - // [2024-03-30 00:00:00 +0000 UTC 2024-03-31 00:00:00 +0000 UTC 2024-04-01 00:00:00 +0000 UTC] - // [yesterday today tomorrow] - // [3 2 1] - // [c b a] + time.Date(2024, 3, 31, 0, 0, 0, 0, time.UTC): "today", + time.Date(2024, 3, 30, 0, 0, 0, 0, time.UTC): "yesterday", + time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC): "tomorrow", + } + + keys1, values1 := maputil.ToSortedSlicesWithComparator(m1, func(a, b time.Time) bool { + return a.Before(b) + }) + + m2 := map[int]string{ + 1: "a", + 3: "c", + 2: "b", + } + keys2, values2 := maputil.ToSortedSlicesWithComparator(m2, func(a, b int) bool { + return a > b + }) + + fmt.Println(keys2) + fmt.Println(values2) + + fmt.Println(keys1) + fmt.Println(values1) + + // Output: + // [3 2 1] + // [c b a] + // [2024-03-30 00:00:00 +0000 UTC 2024-03-31 00:00:00 +0000 UTC 2024-04-01 00:00:00 +0000 UTC] + // [yesterday today tomorrow] } ``` @@ -1144,15 +1179,15 @@ func main() { wg1.Wait() var wg2 sync.WaitGroup - wg2.Add(5) + wg2.Add(5) for j := 0; j < 5; j++ { go func(n int) { val, ok := cm.Get(fmt.Sprintf("%d", n)) fmt.Println(val, ok) - wg2.Done() + wg2.Done() }(j) } - wg2.Wait() + wg2.Wait() // output: (order may change) // 1 true @@ -1198,15 +1233,15 @@ func main() { wg1.Wait() var wg2 sync.WaitGroup - wg2.Add(5) + wg2.Add(5) for j := 0; j < 5; j++ { go func(n int) { val, ok := cm.Get(fmt.Sprintf("%d", n)) fmt.Println(val, ok) - wg2.Done() + wg2.Done() }(j) } - wg2.Wait() + wg2.Wait() // output: (order may change) // 1 true @@ -1296,7 +1331,7 @@ func main() { wg1.Wait() var wg2 sync.WaitGroup - wg2.Add(5) + wg2.Add(5) for j := 0; j < 5; j++ { go func(n int) { cm.Delete(fmt.Sprintf("%d", n)) @@ -1342,7 +1377,7 @@ func main() { wg1.Wait() var wg2 sync.WaitGroup - wg2.Add(5) + wg2.Add(5) for j := 0; j < 5; j++ { go func(n int) { val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n)) @@ -1392,7 +1427,7 @@ func main() { wg1.Wait() var wg2 sync.WaitGroup - wg2.Add(5) + wg2.Add(5) for j := 0; j < 5; j++ { go func(n int) { diff --git a/docs/api/packages/slice.md b/docs/api/packages/slice.md index d43a66d6..8004227f 100644 --- a/docs/api/packages/slice.md +++ b/docs/api/packages/slice.md @@ -2615,7 +2615,7 @@ func main() { func Break[T any](values []T, predicate func(T) bool) ([]T, []T) ``` -示例: +示例:[运行](https://go.dev/play/p/yLYcBTyeQIz) ```go import ( @@ -2648,7 +2648,7 @@ func main() { func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T ``` -示例: +示例:[运行](https://go.dev/play/p/0_2rlLEMBXL) ```go import ( @@ -2675,7 +2675,7 @@ func main() { func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T ``` -示例: +示例:[运行](https://go.dev/play/p/jlQVoelLl2k) ```go import ( diff --git a/docs/en/api/packages/maputil.md b/docs/en/api/packages/maputil.md index 894803e9..5a8e69bc 100644 --- a/docs/en/api/packages/maputil.md +++ b/docs/en/api/packages/maputil.md @@ -44,6 +44,7 @@ import ( - [Minus](#Minus) - [IsDisjoint](#IsDisjoint) - [HasKey](#HasKey) +- [MapToStruct](#MapToStruct) - [ToSortedSlicesDefault](#ToSortedSlicesDefault) - [ToSortedSlicesWithComparator](#ToSortedSlicesWithComparator) - [NewConcurrentMap](#NewConcurrentMap) @@ -994,6 +995,49 @@ func main() { } ``` +### MapToStruct + +

Converts map to struct

+ +Signature: + +```go +func MapToStruct(m map[string]any, structObj any) error +``` + +Example:[Run](https://go.dev/play/p/7wYyVfX38Dp) + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/maputil" +) + +func main() { + personReqMap := map[string]any{ + "name": "Nothin", + "max_age": 35, + "page": 1, + "pageSize": 10, + } + + type PersonReq struct { + Name string `json:"name"` + MaxAge int `json:"max_age"` + Page int `json:"page"` + PageSize int `json:"pageSize"` + } + var personReq PersonReq + _ = maputil.MapToStruct(personReqMap, &personReq) + fmt.Println(personReq) + + // Output: + // {Nothin 35 1 10} +} +``` + ### ToSortedSlicesDefault

@@ -1005,7 +1049,7 @@ Translate the key and value of the map into two slices that are sorted in ascend func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V) ``` -Example:[Run](Todo) +Example:[Run](https://go.dev/play/p/43gEM2po-qy) ```go package main @@ -1017,19 +1061,19 @@ import ( func main() { m := map[int]string{ - 1: "a", - 3: "c", - 2: "b", - } + 1: "a", + 3: "c", + 2: "b", + } - keys, values := ToSortedSlicesDefault(m) + keys, values := maputil.ToSortedSlicesDefault(m) - fmt.Println(keys) - fmt.Println(values) + fmt.Println(keys) + fmt.Println(values) - // Output: - // [1 2 3] - // [a b c] + // Output: + // [1 2 3] + // [a b c] } ``` @@ -1045,7 +1089,7 @@ Translate the key and value of the map into two slices that are sorted according func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V) ``` -Example:[Run](Todo) +Example:[Run](https://go.dev/play/p/0nlPo6YLdt3) ```go package main @@ -1057,35 +1101,35 @@ import ( func main() { m1 := map[time.Time]string{ - time.Date(2024, 3, 31, 0, 0, 0, 0, time.UTC): "today", - time.Date(2024, 3, 30, 0, 0, 0, 0, time.UTC): "yesterday", - time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC): "tomorrow", - } - - keys1, values1 := ToSortedSlicesWithComparator(m1, func(a, b time.Time) bool { - return a.Before(b) - }) - - m2 := map[int]string{ - 1: "a", - 3: "c", - 2: "b", - } - keys2, values2 := ToSortedSlicesWithComparator(m2, func(a, b int) bool { - return a > b - }) - - fmt.Println(keys2) - fmt.Println(values2) - - fmt.Println(keys1) - fmt.Println(values1) - - // Output: - // [2024-03-30 00:00:00 +0000 UTC 2024-03-31 00:00:00 +0000 UTC 2024-04-01 00:00:00 +0000 UTC] - // [yesterday today tomorrow] + time.Date(2024, 3, 31, 0, 0, 0, 0, time.UTC): "today", + time.Date(2024, 3, 30, 0, 0, 0, 0, time.UTC): "yesterday", + time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC): "tomorrow", + } + + keys1, values1 := maputil.ToSortedSlicesWithComparator(m1, func(a, b time.Time) bool { + return a.Before(b) + }) + + m2 := map[int]string{ + 1: "a", + 3: "c", + 2: "b", + } + keys2, values2 := maputil.ToSortedSlicesWithComparator(m2, func(a, b int) bool { + return a > b + }) + + fmt.Println(keys2) + fmt.Println(values2) + + fmt.Println(keys1) + fmt.Println(values1) + + // Output: // [3 2 1] // [c b a] + // [2024-03-30 00:00:00 +0000 UTC 2024-03-31 00:00:00 +0000 UTC 2024-04-01 00:00:00 +0000 UTC] + // [yesterday today tomorrow] } ``` @@ -1152,15 +1196,15 @@ func main() { var wg2 sync.WaitGroup - wg2.Add(5) - for j := 0; j < 5; j++ { - go func(n int) { - val, ok := cm.Get(fmt.Sprintf("%d", n)) - fmt.Println(val, ok) - wg2.Done() - }(j) - } - wg2.Wait() + wg2.Add(5) + for j := 0; j < 5; j++ { + go func(n int) { + val, ok := cm.Get(fmt.Sprintf("%d", n)) + fmt.Println(val, ok) + wg2.Done() + }(j) + } + wg2.Wait() // output: (order may change) // 1 true @@ -1207,15 +1251,15 @@ func main() { var wg2 sync.WaitGroup - wg2.Add(5) - for j := 0; j < 5; j++ { - go func(n int) { - val, ok := cm.Get(fmt.Sprintf("%d", n)) - fmt.Println(val, ok) - wg2.Done() - }(j) - } - wg2.Wait() + wg2.Add(5) + for j := 0; j < 5; j++ { + go func(n int) { + val, ok := cm.Get(fmt.Sprintf("%d", n)) + fmt.Println(val, ok) + wg2.Done() + }(j) + } + wg2.Wait() // output: (order may change) // 1 true @@ -1305,7 +1349,7 @@ func main() { wg1.Wait() var wg2 sync.WaitGroup - wg2.Add(5) + wg2.Add(5) for j := 0; j < 5; j++ { go func(n int) { cm.Delete(fmt.Sprintf("%d", n)) @@ -1352,7 +1396,7 @@ func main() { wg1.Wait() var wg2 sync.WaitGroup - wg2.Add(5) + wg2.Add(5) for j := 0; j < 5; j++ { go func(n int) { val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n)) @@ -1404,7 +1448,7 @@ func main() { wg1.Wait() var wg2 sync.WaitGroup - wg2.Add(5) + wg2.Add(5) for j := 0; j < 5; j++ { go func(n int) { ok := cm.Has(fmt.Sprintf("%d", n)) diff --git a/docs/en/api/packages/slice.md b/docs/en/api/packages/slice.md index 381152a1..f8b38a0c 100644 --- a/docs/en/api/packages/slice.md +++ b/docs/en/api/packages/slice.md @@ -2612,7 +2612,7 @@ func main() { func Break[T any](values []T, predicate func(T) bool) ([]T, []T) ``` -Example: +Example:[Run](https://go.dev/play/p/yLYcBTyeQIz) ```go import ( @@ -2645,7 +2645,7 @@ func main() { func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T ``` -Example: +Example:[Run](https://go.dev/play/p/0_2rlLEMBXL) ```go import ( @@ -2655,7 +2655,7 @@ import ( func main() { nums := []int{1, 2, 3, 4, 5} - padded := RightPadding(nums, 0, 3) + padded := slice.RightPadding(nums, 0, 3) fmt.Println(padded) // Output: // [1 2 3 4 5 0 0 0] @@ -2672,7 +2672,7 @@ func main() { func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T ``` -Example: +Example:[Run](https://go.dev/play/p/jlQVoelLl2k) ```go import ( @@ -2682,7 +2682,7 @@ import ( func main() { nums := []int{1, 2, 3, 4, 5} - padded := LeftPadding(nums, 0, 3) + padded := slice.LeftPadding(nums, 0, 3) fmt.Println(padded) // Output: // [0 0 0 1 2 3 4 5] diff --git a/maputil/map.go b/maputil/map.go index b8cd70af..6cb9f6a6 100644 --- a/maputil/map.go +++ b/maputil/map.go @@ -310,7 +310,7 @@ func HasKey[K comparable, V any](m map[K]V, key K) bool { } // MapToStruct converts map to struct -// Play: todo +// Play: https://go.dev/play/p/7wYyVfX38Dp func MapToStruct(m map[string]any, structObj any) error { for k, v := range m { err := setStructField(structObj, k, v) @@ -389,6 +389,7 @@ func getFieldNameByJsonTag(structObj any, jsonTag string) string { } // ToSortedSlicesDefault converts a map to two slices sorted by key: one for the keys and another for the values. +// Play: https://go.dev/play/p/43gEM2po-qy func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V) { keys := make([]K, 0, len(m)) @@ -413,6 +414,7 @@ func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V) { // ToSortedSlicesWithComparator converts a map to two slices sorted by key and using a custom comparison function: // one for the keys and another for the values. +// Play: https://go.dev/play/p/0nlPo6YLdt3 func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V) { keys := make([]K, 0, len(m)) diff --git a/slice/slice.go b/slice/slice.go index 6cf9e717..3c0066a6 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -1254,7 +1254,7 @@ func Partition[T any](slice []T, predicates ...func(item T) bool) [][]T { } // Breaks a list into two parts at the point where the predicate for the first time is true. -// Play: Todo +// Play: https://go.dev/play/p/yLYcBTyeQIz func Break[T any](values []T, predicate func(T) bool) ([]T, []T) { a := make([]T, 0) b := make([]T, 0) @@ -1289,7 +1289,7 @@ func Random[T any](slice []T) (val T, idx int) { } // RightPadding adds padding to the right end of a slice. -// Play: Todo +// Play: https://go.dev/play/p/0_2rlLEMBXL func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T { if paddingLength == 0 { return slice @@ -1301,7 +1301,7 @@ func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T { } // LeftPadding adds padding to the left begin of a slice. -// Play: Todo +// Play: https://go.dev/play/p/jlQVoelLl2k func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T { if paddingLength == 0 { return slice