shuffle array in Go

2020-05-13 20:22发布

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?

标签: arrays go
8条回答
Fickle 薄情
2楼-- · 2020-05-13 21:07

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 than BenchmarkPerm30, 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 example rand.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)
查看更多
啃猪蹄的小仙女
3楼-- · 2020-05-13 21:14

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.

查看更多
登录 后发表回答