shuffle array in Go
I tried to translate the following Python code to Go
import random
list = [i for i in range(1, 25)]
random.shuffle(list)
print(list)
but found my Go version lengthy and awkward because there is no shuffle function and I had to implement interfaces and convert types.
What would be an idiomatic Go version of my code?
Solution 1:
dystroy's answer is perfectly reasonable, but it's also possible to shuffle without allocating any additional slices.
for i := range slice {
j := rand.Intn(i + 1)
slice[i], slice[j] = slice[j], slice[i]
}
See this Wikipedia article for more details on the algorithm. rand.Perm
actually uses this algorithm internally as well.
Solution 2:
As your list is just the integers from 1 to 25, you can use Perm :
list := rand.Perm(25)
for i, _ := range list {
list[i]++
}
Note that using a permutation given by rand.Perm
is an effective way to shuffle any array.
dest := make([]int, len(src))
perm := rand.Perm(len(src))
for i, v := range perm {
dest[v] = src[i]
}
Solution 3:
Since 1.10 Go includes an official Fisher-Yates shuffle function.
Documentation: pkg/math/rand/#Shuffle
math/rand: add Shuffle
Shuffle uses the Fisher-Yates algorithm.
Since this is new API, it affords us the opportunity to use a much faster
Int31n
implementation that mostly avoids division.As a result,
BenchmarkPerm30ViaShuffle
is about 30% faster thanBenchmarkPerm30
, despite requiring a separate initialization loop and using function calls to swap elements.
See also the original CL 51891
First, as commented by shelll:
Do not forget to seed the random, or you will always get the same order.
For examplerand.Seed(time.Now().UnixNano())
Example:
words := strings.Fields("ink runs from the corners of my mouth")
rand.Shuffle(len(words), func(i, j int) {
words[i], words[j] = words[j], words[i]
})
fmt.Println(words)