从Go切片中随机选择一个值

huangapple go评论126阅读模式
英文:

Pick a random value from a Go Slice

问题

情况:

我有一个值的切片,并且需要从中随机选择一个值。然后我想将它与一个固定的字符串连接起来。这是我目前的代码:

  1. func main() {
  2. //创建reasons切片并将原因追加到其中
  3. reasons := make([]string, 0)
  4. reasons = append(reasons,
  5. "Locked out",
  6. "Pipes broke",
  7. "Food poisoning",
  8. "Not feeling well")
  9. message := fmt.Sprint("Gonna work from home...", pick a random reason )
  10. }

问题:

是否有一个内置的函数可以帮助我完成"pick a random reason"这部分的功能?

英文:

Situation:

I've a slice of values and need to pick up a randomly chosen value from it. Then I want to concatenate it with a fixed string. This is my code so far:

  1. func main() {
  2. //create the reasons slice and append reasons to it
  3. reasons := make([]string, 0)
  4. reasons = append(reasons,
  5. "Locked out",
  6. "Pipes broke",
  7. "Food poisoning",
  8. "Not feeling well")
  9. message := fmt.Sprint("Gonna work from home...", pick a random reason )
  10. }

Question:

Is there a built-in function, which can help me by doing the "pick a random reason" part?

答案1

得分: 148

使用rand包中的Intn函数来选择一个随机索引。

  1. import (
  2. "math/rand"
  3. "time"
  4. )
  5. // ...
  6. rand.Seed(time.Now().Unix()) // 初始化全局伪随机生成器
  7. message := fmt.Sprint("Gonna work from home...", reasons[rand.Intn(len(reasons))])
  8. 另一种解决方案是使用`Rand`对象
  9. s := rand.NewSource(time.Now().Unix())
  10. r := rand.New(s) // 初始化局部伪随机生成器
  11. r.Intn(len(reasons))
英文:

Use function Intn from rand package to select a random index.

  1. import (
  2. "math/rand"
  3. "time"
  4. )
  5. // ...
  6. rand.Seed(time.Now().Unix()) // initialize global pseudo random generator
  7. message := fmt.Sprint("Gonna work from home...", reasons[rand.Intn(len(reasons))])

Other solution is to use Rand object.

  1. s := rand.NewSource(time.Now().Unix())
  2. r := rand.New(s) // initialize local pseudorandom generator
  3. r.Intn(len(reasons))

答案2

得分: 27

只需选择一个随机整数模切片长度:

  1. rand.Seed(time.Now().Unix())
  2. reasons := []string{
  3. "被锁在外面",
  4. "管道坏了",
  5. "食物中毒",
  6. "感觉不舒服",
  7. }
  8. n := rand.Int() % len(reasons)
  9. fmt.Print("要在家工作了...", reasons[n])

Playground: http://play.golang.org/p/fEHElLJrEZ。 (注意关于rand.Seed的注释。)

英文:

Just pick a random integer mod slice length:

  1. rand.Seed(time.Now().Unix())
  2. reasons := []string{
  3. "Locked out",
  4. "Pipes broke",
  5. "Food poisoning",
  6. "Not feeling well",
  7. }
  8. n := rand.Int() % len(reasons)
  9. fmt.Print("Gonna work from home...", reasons[n])

Playground: http://play.golang.org/p/fEHElLJrEZ. (Note the commend about rand.Seed.)

答案3

得分: -2

由于这个问题在谷歌的搜索结果中仍然显示为Golang随机字符串生成的前几个结果,我想分享一下我一直在使用的解决方案。

这是我正在使用的解决方案:

  1. package main
  2. import (
  3. "fmt"
  4. "strings"
  5. "time"
  6. )
  7. var (
  8. opts = strings.Split("option1,option2,option3", ",")
  9. start = time.Now()
  10. )
  11. func main() {
  12. fmt.Println(getRandomOpt(), time.Since(start))
  13. fmt.Println(getRandomOpt(), time.Since(start))
  14. fmt.Println(getRandomOpt(), time.Since(start))
  15. fmt.Println(getRandomOpt(), time.Since(start))
  16. fmt.Println(getRandomOpt(), time.Since(start))
  17. fmt.Println(getRandomOpt(), time.Since(start))
  18. fmt.Println(getRandomOpt(), time.Since(start))
  19. fmt.Println(getRandomOpt(), time.Since(start))
  20. fmt.Println(getRandomOpt(), time.Since(start))
  21. }
  22. func getRandomOpt() string {
  23. len := len(opts)
  24. n := uint32(0)
  25. if len > 0 {
  26. n = getRandomUint32() % uint32(len)
  27. }
  28. return opts[n]
  29. }
  30. func getRandomUint32() uint32 {
  31. x := time.Now().UnixNano()
  32. return uint32((x >> 32) ^ x)
  33. }

结果如下:

  1. option2 665ns
  2. option1 41.406μs
  3. option1 44.817μs
  4. option3 47.329μs
  5. option1 49.725μs
  6. option3 52μs
  7. option2 54.393μs
  8. option2 56.798μs
  9. option1 59.098μs

源代码方面,我从fastrand库中复制了getRandomUint32()函数:https://github.com/valyala/fastrand

还有上面提出的解决方案。性能上并没有太大的差异,但我想分享一下结果。

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "strings"
  6. "time"
  7. )
  8. var (
  9. opts = strings.Split("option1,option2,option3", ",")
  10. start = time.Now()
  11. )
  12. func main() {
  13. rand.Seed(start.Unix())
  14. fmt.Println(getRandomOpt(), time.Since(start))
  15. fmt.Println(getRandomOpt(), time.Since(start))
  16. fmt.Println(getRandomOpt(), time.Since(start))
  17. fmt.Println(getRandomOpt(), time.Since(start))
  18. fmt.Println(getRandomOpt(), time.Since(start))
  19. fmt.Println(getRandomOpt(), time.Since(start))
  20. fmt.Println(getRandomOpt(), time.Since(start))
  21. fmt.Println(getRandomOpt(), time.Since(start))
  22. fmt.Println(getRandomOpt(), time.Since(start))
  23. }
  24. func getRandomOpt() string {
  25. return opts[rand.Intn(len(opts))]
  26. }

结果如下:

  1. option3 11.865μs
  2. option2 48.415μs
  3. option3 52.809μs
  4. option1 55.536μs
  5. option3 58.191μs
  6. option3 60.793μs
  7. option1 63.391μs
  8. option2 65.982μs
  9. option2 68.601μs

这些结果只是在本地运行了几次,并且我选择了似乎是中间结果的值。在迭代和其他方面肯定还有更多的工作要做,但我只是想分享一下我目前的进展。

英文:

Since this still shows up in Google's top results for Golang random string generation, I wanted to share what I have been working with.

Here is the solution I am using:

  1. package main
  2. import (
  3. "fmt"
  4. "strings"
  5. "time"
  6. )
  7. var (
  8. opts = strings.Split("option1,option2,option3", ",")
  9. start = time.Now()
  10. )
  11. func main() {
  12. fmt.Println(getRandomOpt(), time.Since(start))
  13. fmt.Println(getRandomOpt(), time.Since(start))
  14. fmt.Println(getRandomOpt(), time.Since(start))
  15. fmt.Println(getRandomOpt(), time.Since(start))
  16. fmt.Println(getRandomOpt(), time.Since(start))
  17. fmt.Println(getRandomOpt(), time.Since(start))
  18. fmt.Println(getRandomOpt(), time.Since(start))
  19. fmt.Println(getRandomOpt(), time.Since(start))
  20. fmt.Println(getRandomOpt(), time.Since(start))
  21. }
  22. func getRandomOpt() string {
  23. len := len(opts)
  24. n := uint32(0)
  25. if len > 0 {
  26. n = getRandomUint32() % uint32(len)
  27. }
  28. return opts[n]
  29. }
  30. func getRandomUint32() uint32 {
  31. x := time.Now().UnixNano()
  32. return uint32((x >> 32) ^ x)
  33. }

And results:

  1. option2 665ns
  2. option1 41.406µs
  3. option1 44.817µs
  4. option3 47.329µs
  5. option1 49.725µs
  6. option3 52µs
  7. option2 54.393µs
  8. option2 56.798µs
  9. option1 59.098µs

Source wise, I copied getRandomUint32() from fastrand: https://github.com/valyala/fastrand

And the solution proposed above. Performance isn't all that different, but I wanted to share results.

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "strings"
  6. "time"
  7. )
  8. var (
  9. opts = strings.Split("option1,option2,option3", ",")
  10. start = time.Now()
  11. )
  12. func main() {
  13. rand.Seed(start.Unix())
  14. fmt.Println(getRandomOpt(), time.Since(start))
  15. fmt.Println(getRandomOpt(), time.Since(start))
  16. fmt.Println(getRandomOpt(), time.Since(start))
  17. fmt.Println(getRandomOpt(), time.Since(start))
  18. fmt.Println(getRandomOpt(), time.Since(start))
  19. fmt.Println(getRandomOpt(), time.Since(start))
  20. fmt.Println(getRandomOpt(), time.Since(start))
  21. fmt.Println(getRandomOpt(), time.Since(start))
  22. fmt.Println(getRandomOpt(), time.Since(start))
  23. }
  24. func getRandomOpt() string {
  25. return opts[rand.Intn(len(opts))]
  26. }

And results:

  1. option3 11.865µs
  2. option2 48.415µs
  3. option3 52.809µs
  4. option1 55.536µs
  5. option3 58.191µs
  6. option3 60.793µs
  7. option1 63.391µs
  8. option2 65.982µs
  9. option2 68.601µs

These results were only run a few times locally and I grabbed what appeared to be the median result. There is certainly more work to be done in terms of iterations and whatnot, but I just wanted to share what I have.

huangapple
  • 本文由 发表于 2015年11月30日 16:55:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/33994677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定