feat: collection 包新增 ConvertSliceToBatches、ConvertMapKeysToBatches、ConvertMapValuesToBatches 函数,用于将切片或 map 转换为按特定数量分批的批次切片
This commit is contained in:
parent
6cc158d43a
commit
9dba7ffe19
|
@ -1,5 +1,55 @@
|
|||
package collection
|
||||
|
||||
// ConvertSliceToBatches 将切片 s 转换为分批次的切片,当 batchSize 小于等于 0 或者 s 长度为 0 时,将会返回 nil
|
||||
func ConvertSliceToBatches[S ~[]V, V any](s S, batchSize int) []S {
|
||||
if len(s) == 0 || batchSize <= 0 {
|
||||
return nil
|
||||
}
|
||||
var batches = make([]S, 0, len(s)/batchSize+1)
|
||||
for i := 0; i < len(s); i += batchSize {
|
||||
var end = i + batchSize
|
||||
if end > len(s) {
|
||||
end = len(s)
|
||||
}
|
||||
batches = append(batches, s[i:end])
|
||||
}
|
||||
return batches
|
||||
}
|
||||
|
||||
// ConvertMapKeysToBatches 将映射的键转换为分批次的切片,当 batchSize 小于等于 0 或者 m 长度为 0 时,将会返回 nil
|
||||
func ConvertMapKeysToBatches[M ~map[K]V, K comparable, V any](m M, batchSize int) [][]K {
|
||||
if len(m) == 0 || batchSize <= 0 {
|
||||
return nil
|
||||
}
|
||||
var batches = make([][]K, 0, len(m)/batchSize+1)
|
||||
var keys = ConvertMapKeysToSlice(m)
|
||||
for i := 0; i < len(keys); i += batchSize {
|
||||
var end = i + batchSize
|
||||
if end > len(keys) {
|
||||
end = len(keys)
|
||||
}
|
||||
batches = append(batches, keys[i:end])
|
||||
}
|
||||
return batches
|
||||
}
|
||||
|
||||
// ConvertMapValuesToBatches 将映射的值转换为分批次的切片,当 batchSize 小于等于 0 或者 m 长度为 0 时,将会返回 nil
|
||||
func ConvertMapValuesToBatches[M ~map[K]V, K comparable, V any](m M, batchSize int) [][]V {
|
||||
if len(m) == 0 || batchSize <= 0 {
|
||||
return nil
|
||||
}
|
||||
var batches = make([][]V, 0, len(m)/batchSize+1)
|
||||
var values = ConvertMapValuesToSlice(m)
|
||||
for i := 0; i < len(values); i += batchSize {
|
||||
var end = i + batchSize
|
||||
if end > len(values) {
|
||||
end = len(values)
|
||||
}
|
||||
batches = append(batches, values[i:end])
|
||||
}
|
||||
return batches
|
||||
}
|
||||
|
||||
// ConvertSliceToAny 将切片转换为任意类型的切片
|
||||
func ConvertSliceToAny[S ~[]V, V any](s S) []any {
|
||||
if len(s) == 0 {
|
||||
|
|
|
@ -4,8 +4,33 @@ import (
|
|||
"fmt"
|
||||
"github.com/kercylan98/minotaur/utils/collection"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func ExampleConvertSliceToBatches() {
|
||||
result := collection.ConvertSliceToBatches([]int{1, 2, 3}, 2)
|
||||
for _, v := range result {
|
||||
fmt.Println(v)
|
||||
}
|
||||
// Output:
|
||||
// [1 2]
|
||||
// [3]
|
||||
}
|
||||
|
||||
func ExampleConvertMapKeysToBatches() {
|
||||
result := collection.ConvertMapKeysToBatches(map[int]int{1: 1, 2: 2, 3: 3}, 2)
|
||||
fmt.Println(len(result))
|
||||
// Output:
|
||||
// 2
|
||||
}
|
||||
|
||||
func ExampleConvertMapValuesToBatches() {
|
||||
result := collection.ConvertMapValuesToBatches(map[int]int{1: 1, 2: 2, 3: 3}, 2)
|
||||
fmt.Println(len(result))
|
||||
// Output:
|
||||
// 2
|
||||
}
|
||||
|
||||
func ExampleConvertSliceToAny() {
|
||||
result := collection.ConvertSliceToAny([]int{1, 2, 3})
|
||||
fmt.Println(reflect.TypeOf(result).String(), len(result))
|
||||
|
@ -60,6 +85,7 @@ func ExampleConvertSliceToBoolMap() {
|
|||
|
||||
func ExampleConvertMapKeysToSlice() {
|
||||
result := collection.ConvertMapKeysToSlice(map[int]int{1: 1, 2: 2, 3: 3})
|
||||
sort.Ints(result)
|
||||
for i, v := range result {
|
||||
fmt.Println(i, v)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,90 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestConvertSliceToBatches(t *testing.T) {
|
||||
var cases = []struct {
|
||||
name string
|
||||
input []int
|
||||
batch int
|
||||
expected [][]int
|
||||
}{
|
||||
{name: "TestConvertSliceToBatches_NonEmpty", input: []int{1, 2, 3}, batch: 2, expected: [][]int{{1, 2}, {3}}},
|
||||
{name: "TestConvertSliceToBatches_Empty", input: []int{}, batch: 2, expected: nil},
|
||||
{name: "TestConvertSliceToBatches_Nil", input: nil, batch: 2, expected: nil},
|
||||
{name: "TestConvertSliceToBatches_NonPositive", input: []int{1, 2, 3}, batch: 0, expected: nil},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
actual := collection.ConvertSliceToBatches(c.input, c.batch)
|
||||
if len(actual) != len(c.expected) {
|
||||
t.Errorf("expected: %v, actual: %v", c.expected, actual)
|
||||
}
|
||||
for i := 0; i < len(actual); i++ {
|
||||
av, ev := actual[i], c.expected[i]
|
||||
if len(av) != len(ev) {
|
||||
t.Errorf("expected: %v, actual: %v", c.expected, actual)
|
||||
}
|
||||
for j := 0; j < len(av); j++ {
|
||||
aj, ej := av[j], ev[j]
|
||||
if reflect.TypeOf(aj).Kind() != reflect.TypeOf(ej).Kind() {
|
||||
t.Errorf("expected: %v, actual: %v", c.expected, actual)
|
||||
}
|
||||
if aj != ej {
|
||||
t.Errorf("expected: %v, actual: %v", c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertMapKeysToBatches(t *testing.T) {
|
||||
var cases = []struct {
|
||||
name string
|
||||
input map[int]int
|
||||
batch int
|
||||
expected [][]int
|
||||
}{
|
||||
{name: "TestConvertMapKeysToBatches_NonEmpty", input: map[int]int{1: 1, 2: 2, 3: 3}, batch: 2, expected: [][]int{{1, 2}, {3}}},
|
||||
{name: "TestConvertMapKeysToBatches_Empty", input: map[int]int{}, batch: 2, expected: nil},
|
||||
{name: "TestConvertMapKeysToBatches_Nil", input: nil, batch: 2, expected: nil},
|
||||
{name: "TestConvertMapKeysToBatches_NonPositive", input: map[int]int{1: 1, 2: 2, 3: 3}, batch: 0, expected: nil},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
actual := collection.ConvertMapKeysToBatches(c.input, c.batch)
|
||||
if len(actual) != len(c.expected) {
|
||||
t.Errorf("expected: %v, actual: %v", c.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertMapValuesToBatches(t *testing.T) {
|
||||
var cases = []struct {
|
||||
name string
|
||||
input map[int]int
|
||||
batch int
|
||||
expected [][]int
|
||||
}{
|
||||
{name: "TestConvertMapValuesToBatches_NonEmpty", input: map[int]int{1: 1, 2: 2, 3: 3}, batch: 2, expected: [][]int{{1, 2}, {3}}},
|
||||
{name: "TestConvertMapValuesToBatches_Empty", input: map[int]int{}, batch: 2, expected: nil},
|
||||
{name: "TestConvertMapValuesToBatches_Nil", input: nil, batch: 2, expected: nil},
|
||||
{name: "TestConvertMapValuesToBatches_NonPositive", input: map[int]int{1: 1, 2: 2, 3: 3}, batch: 0, expected: nil},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
actual := collection.ConvertMapValuesToBatches(c.input, c.batch)
|
||||
if len(actual) != len(c.expected) {
|
||||
t.Errorf("expected: %v, actual: %v", c.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertSliceToAny(t *testing.T) {
|
||||
var cases = []struct {
|
||||
name string
|
||||
|
|
Loading…
Reference in New Issue