diff --git a/docs/api/packages/random.md b/docs/api/packages/random.md index c08ea148..3f58bff0 100644 --- a/docs/api/packages/random.md +++ b/docs/api/packages/random.md @@ -26,6 +26,7 @@ import ( - [RandInt](#RandInt) - [RandString](#RandString) - [RandFromGivenSlice](#RandFromGivenSlice) +- [RandSliceFromGivenSlice](#RandSliceFromGivenSlice) - [RandUpper](#RandUpper) - [RandLower](#RandLower) - [RandNumeral](#RandNumeral) @@ -150,6 +151,33 @@ func main() { } ``` +### RandSliceFromGivenSlice + +

从给定切片中生成长度为 num 的随机切片

+ +函数签名: + +```go +func RandSliceFromGivenSlice[T any](slice []T, num int, repeatable bool) []T +``` + +示例:[运行]() + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/random" +) + +func main() { + goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon","mango", "nectarine", "orange"} + chosen3goods := random.RandSliceFromGivenSlice(goods, 3, false) + fmt.Println(chosen3goods) +} +``` + ### RandUpper

生成给定长度的随机大写字母字符串

diff --git a/docs/en/api/packages/random.md b/docs/en/api/packages/random.md index 173ee49c..ba2b7ce3 100644 --- a/docs/en/api/packages/random.md +++ b/docs/en/api/packages/random.md @@ -25,6 +25,8 @@ import ( - [RandBytes](#RandBytes) - [RandInt](#RandInt) - [RandString](#RandString) +- [RandFromGivenSlice](#RandFromGivenSlice) +- [RandSliceFromGivenSlice](#RandSliceFromGivenSlice) - [RandUpper](#RandUpper) - [RandLower](#RandLower) - [RandNumeral](#RandNumeral) @@ -148,6 +150,33 @@ func main() { } ``` +### RandSliceFromGivenSlice + +

Generate a random slice of length num from given slice.

+ +Signature: + +```go +func RandSliceFromGivenSlice[T any](slice []T, num int, repeatable bool) []T +``` + +Example:[Run]() + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/random" +) + +func main() { + goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon", "mango", "nectarine", "orange"} + chosen3goods := random.RandSliceFromGivenSlice(goods, 3, false) + fmt.Println(chosen3goods) +} +``` + ### RandUpper

Generate a random upper case string

diff --git a/random/random.go b/random/random.go index 1a7b9707..0174daf0 100644 --- a/random/random.go +++ b/random/random.go @@ -186,6 +186,7 @@ func RandStringSlice(charset string, sliceLen, strLen int) []string { } // RandFromGivenSlice generate a random element from given slice. +// Play: todo func RandFromGivenSlice[T any](slice []T) T { if len(slice) == 0 { var zero T @@ -194,6 +195,35 @@ func RandFromGivenSlice[T any](slice []T) T { return slice[rand.Intn(len(slice))] } +// RandSliceFromGivenSlice generate a random slice of length num from given slice. +// - If repeatable is true, the generated slice may contain duplicate elements. +// +// Play: todo +func RandSliceFromGivenSlice[T any](slice []T, num int, repeatable bool) []T { + if num <= 0 || len(slice) == 0 { + return slice + } + + if !repeatable && num > len(slice) { + num = len(slice) + } + + result := make([]T, num) + if repeatable { + for i := range result { + result[i] = slice[rand.Intn(len(slice))] + } + } else { + shuffled := make([]T, len(slice)) + copy(shuffled, slice) + rand.Shuffle(len(shuffled), func(i, j int) { + shuffled[i], shuffled[j] = shuffled[j], shuffled[i] + }) + result = shuffled[:num] + } + return result +} + // RandUpper generate a random upper case string of specified length. // Play: https://go.dev/play/p/29QfOh0DVuh func RandUpper(length int) string { diff --git a/random/random_example_test.go b/random/random_example_test.go index bd1a728e..05cbaec2 100644 --- a/random/random_example_test.go +++ b/random/random_example_test.go @@ -47,18 +47,15 @@ func ExampleRandFromGivenSlice() { goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon", "mango", "nectarine", "orange"} - isInGoods := false result := RandFromGivenSlice(goods) - for _, good := range goods { - if good == result { - isInGoods = true - break - } - } - fmt.Println(isInGoods) + fmt.Println(result) +} - // Output: - // true +func ExampleRandSliceFromGivenSlice() { + goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon", + "mango", "nectarine", "orange"} + chosen3goods := RandSliceFromGivenSlice(goods, 3, false) + fmt.Println(chosen3goods) } func ExampleRandUpper() { diff --git a/random/random_test.go b/random/random_test.go index 500b7eeb..f7df09dc 100644 --- a/random/random_test.go +++ b/random/random_test.go @@ -292,6 +292,46 @@ func TestRandFromGivenSlice(t *testing.T) { assert.Equal(0, emtpyIntResult) } +func TestRandSliceFromGivenSlice(t *testing.T) { + t.Parallel() + assert := internal.NewAssert(t, "TestRandSliceFromGivenSlice") + + randomSet := []any{"a", 8, "王", true, 1.1} + repeatableResult := RandSliceFromGivenSlice(randomSet, 8, true) + assert.Equal(8, len(repeatableResult)) + unrepeatableResult := RandSliceFromGivenSlice(randomSet, 8, false) + assert.Equal(len(randomSet), len(unrepeatableResult)) + + var findCount int + for _, v := range repeatableResult { + for _, vv := range randomSet { + if v == vv { + findCount++ + } + } + } + assert.Equal(8, findCount) + findCount = 0 + + for _, v := range unrepeatableResult { + for _, vv := range randomSet { + if v == vv { + findCount++ + } + } + } + assert.Equal(len(randomSet), findCount) + + emptyAnyRandomSet := []any{} + emptyAnyResult := RandSliceFromGivenSlice(emptyAnyRandomSet, 3, true) + assert.Equal([]any{}, emptyAnyResult) + + emptyIntRandomSet := []int{} + emtpyIntResult := RandSliceFromGivenSlice(emptyIntRandomSet, 3, true) + assert.Equal([]int{}, emtpyIntResult) + +} + func TestRandBool(t *testing.T) { t.Parallel() assert := internal.NewAssert(t, "TestRandBool")