diff --git a/random/random.go b/random/random.go index b6fc1aa..d551d74 100644 --- a/random/random.go +++ b/random/random.go @@ -114,3 +114,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_example_test.go b/random/random_example_test.go index 9c51d66..e2f6032 100644 --- a/random/random_example_test.go +++ b/random/random_example_test.go @@ -123,3 +123,14 @@ func ExampleUUIdV4() { // Output: // true } + +func ExampleRandUniqueIntSlice() { + result := RandUniqueIntSlice(5, 0, 10) + + if len(result) == 5 { + fmt.Println("ok") + } + + // Output: + // ok +} diff --git a/random/random_test.go b/random/random_test.go index c4b693b..72c8be3 100644 --- a/random/random_test.go +++ b/random/random_test.go @@ -103,3 +103,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 +}