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

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

Pick a random value from a Go Slice

问题

情况:

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

func main() {
    //创建reasons切片并将原因追加到其中
    reasons := make([]string, 0)
    reasons = append(reasons,
        "Locked out",
        "Pipes broke",
        "Food poisoning",
        "Not feeling well")

    message := fmt.Sprint("Gonna work from home...", pick a random reason )
}

问题:

是否有一个内置的函数可以帮助我完成"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:

func main() {
//create the reasons slice and append reasons to it
reasons := make([]string, 0)
reasons = append(reasons,
	"Locked out",
	"Pipes broke",
	"Food poisoning",
	"Not feeling well")

message := fmt.Sprint("Gonna work from home...", pick a random reason )
}

Question:

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

答案1

得分: 148

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

import (
  "math/rand"
  "time"
)

// ...

rand.Seed(time.Now().Unix()) // 初始化全局伪随机生成器
message := fmt.Sprint("Gonna work from home...", reasons[rand.Intn(len(reasons))])

另一种解决方案是使用`Rand`对象

s := rand.NewSource(time.Now().Unix())
r := rand.New(s) // 初始化局部伪随机生成器
r.Intn(len(reasons))
英文:

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

import (
  "math/rand"
  "time"
)

// ...

rand.Seed(time.Now().Unix()) // initialize global pseudo random generator
message := fmt.Sprint("Gonna work from home...", reasons[rand.Intn(len(reasons))])

Other solution is to use Rand object.

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

答案2

得分: 27

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

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

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

英文:

Just pick a random integer mod slice length:

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

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

答案3

得分: -2

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

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

package main

import (
  "fmt"
  "strings"
  "time"
)

var (
  opts  = strings.Split("option1,option2,option3", ",")
  start = time.Now()
)

func main() {
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
}

func getRandomOpt() string {
  len := len(opts)
  n := uint32(0)
  if len > 0 {
    n = getRandomUint32() % uint32(len)
  }
  return opts[n]
}

func getRandomUint32() uint32 {
  x := time.Now().UnixNano()
  return uint32((x >> 32) ^ x)
}

结果如下:

option2 665ns
option1 41.406μs
option1 44.817μs
option3 47.329μs
option1 49.725μs
option3 52μs
option2 54.393μs
option2 56.798μs
option1 59.098μs

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

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

package main

import (
  "fmt"
  "math/rand"
  "strings"
  "time"
)

var (
  opts  = strings.Split("option1,option2,option3", ",")
  start = time.Now()
)

func main() {
  rand.Seed(start.Unix())
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
}

func getRandomOpt() string {
  return opts[rand.Intn(len(opts))]
}

结果如下:

option3 11.865μs
option2 48.415μs
option3 52.809μs
option1 55.536μs
option3 58.191μs
option3 60.793μs
option1 63.391μs
option2 65.982μs
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:

package main

import (
  "fmt"
  "strings"
  "time"
)

var (
  opts  = strings.Split("option1,option2,option3", ",")
  start = time.Now()
)

func main() {
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
}

func getRandomOpt() string {
  len := len(opts)
  n := uint32(0)
  if len > 0 {
    n = getRandomUint32() % uint32(len)
  }
  return opts[n]
}

func getRandomUint32() uint32 {
  x := time.Now().UnixNano()
  return uint32((x >> 32) ^ x)
}

And results:

option2 665ns
option1 41.406µs
option1 44.817µs
option3 47.329µs
option1 49.725µs
option3 52µs
option2 54.393µs
option2 56.798µs
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.

package main

import (
  "fmt"
  "math/rand"
  "strings"
  "time"
)

var (
  opts  = strings.Split("option1,option2,option3", ",")
  start = time.Now()
)

func main() {
  rand.Seed(start.Unix())
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
  fmt.Println(getRandomOpt(), time.Since(start))
}

func getRandomOpt() string {
  return opts[rand.Intn(len(opts))]
}

And results:

option3 11.865µs
option2 48.415µs
option3 52.809µs
option1 55.536µs
option3 58.191µs
option3 60.793µs
option1 63.391µs
option2 65.982µs
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:

确定