diff --git a/docs/random.md b/docs/random.md index b986df4..10e484a 100644 --- a/docs/random.md +++ b/docs/random.md @@ -30,6 +30,7 @@ import ( - [RandNumeral](#RandNumeral) - [RandNumeralOrLetter](#RandNumeralOrLetter) - [UUIdV4](#UUIdV4) +- [RandUniqueIntSlice](#RandUniqueIntSlice)
@@ -245,3 +246,29 @@ func main() { fmt.Println(uuid) } ``` + +### RandUniqueIntSlice + +

Generate a slice of random int of length n that do not repeat.

+ +Signature: + +```go +func RandUniqueIntSlice(n, min, max int) []int +``` + +Example: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/random" +) + +func main() { + result := RandUniqueIntSlice(5, 0, 10) + fmt.Println(result) //[0 4 7 1 5] (random) +} +``` diff --git a/docs/random_zh-CN.md b/docs/random_zh-CN.md index 5c8fffd..645ff48 100644 --- a/docs/random_zh-CN.md +++ b/docs/random_zh-CN.md @@ -30,6 +30,7 @@ import ( - [RandNumeral](#RandNumeral) - [RandNumeralOrLetter](#RandNumeralOrLetter) - [UUIdV4](#UUIdV4) +- [RandUniqueIntSlice](#RandUniqueIntSlice)
@@ -245,3 +246,29 @@ func main() { fmt.Println(uuid) } ``` + +### RandUniqueIntSlice + +

生成一个不重复的长度为n的随机int切片。

+ +函数签名: + +```go +func RandUniqueIntSlice(n, min, max int) []int +``` + +示例: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/random" +) + +func main() { + result := RandUniqueIntSlice(5, 0, 10) + fmt.Println(result) //[0 4 7 1 5] (random) +} +``` diff --git a/random/random.go b/random/random.go index 0e3c383..790ad09 100644 --- a/random/random.go +++ b/random/random.go @@ -101,3 +101,27 @@ func UUIdV4() (string, error) { return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil } + +// RandUniqueIntSlice generate a slice of random int of length n that do not repeat. +func RandUniqueIntSlice(n, min, max int) []int { + if min > max { + return []int{} + } + if n > max-min { + n = max - min + } + + nums := make([]int, n) + used := make(map[int]struct{}, n) + for i := 0; i < n; { + r := RandInt(min, max) + if _, use := used[r]; use { + continue + } + used[r] = struct{}{} + nums[i] = r + i++ + } + + return nums +} diff --git a/random/random_test.go b/random/random_test.go index 1813931..624077b 100644 --- a/random/random_test.go +++ b/random/random_test.go @@ -105,3 +105,36 @@ func TestUUIdV4(t *testing.T) { isUUiDV4 := regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`) assert.Equal(true, isUUiDV4.MatchString(uuid)) } + +func TestRandUniqueIntSlice(t *testing.T) { + assert := internal.NewAssert(t, "TestRandUniqueIntSlice") + + r1 := RandUniqueIntSlice(5, 0, 9) + assert.Equal(len(r1), 5) + if hasDuplicate(r1) { + t.Error("hasDuplicate int") + } + + r2 := RandUniqueIntSlice(20, 0, 10) + assert.Equal(len(r2), 10) + if hasDuplicate(r2) { + t.Error("hasDuplicate int") + } + + r3 := RandUniqueIntSlice(10, 20, 10) + assert.Equal(len(r3), 0) + + r4 := RandUniqueIntSlice(0, 20, 10) + assert.Equal(len(r4), 0) +} + +func hasDuplicate(arr []int) bool { + elements := make(map[int]bool) + for _, v := range arr { + if elements[v] { + return true + } + elements[v] = true + } + return false +}