英文:
How could I pick a random item from a slice with bias towards one end of the slice using Go?
问题
我理解你想要从一个slice
中以某种方式随机选择一个值的方法。以下是代码示例:
rand.Seed(time.Now().UTC().UnixNano())
var db [500]string
log.Println(db[rand.Intn(len(db))])
但是,如果我想要从slice
中以偏向于某一端的方式选择一个随机项,该怎么办呢?根据我的使用情况,我会使用append()
函数不断向slice
中添加新的项。我希望创建一个函数,从slice
中随机选择一个项,偏向于最新添加的项。我最初的想法是使用正态分布
,通过rand.NormFloat64()
来实现,但我不确定如何使用它来达到这个目的。
这个函数应该能够从slice
中选择任何项,但是应该更频繁地选择新添加的项。
英文:
I understand one way to pick a random value from a slice
in Go
:
rand.Seed(time.Now().UTC().UnixNano())
var db [500]string
log.Println(db[rand.Intn(len(db))])
But how would I pick a random item from the slice
, with a bias towards one end of the slice
? For my use case I'll have a slice
that grows over time using append()
. My understanding is that the newest items will be added to the right-hand side of the slice
. I'd like to create a function that picks a random item from the slice
, with bias towards the newest members of the slice
. My first guess is to use a normal distribution
via rand.NormFloat64()
, but I'm not sure how or if I can use it to achieve this.
The function should be capable of picking any item from the slice
, but should pick new items added to the slice
at a much higher frequency.
答案1
得分: 1
假设你对正态分布满意,你可以使用rand.Normfloat64()函数。如果你的数组有20个元素:
int(math.Abs(rand.NormFloat64())*10) % 20
将生成偏向列表开头的数字。而
20 - int(math.Abs(rand.NormFloat64())*10) % 20
将生成偏向列表末尾的数字。
下面是一个演示随机分布的示例。在Go Playground上查看:https://go.dev/play/p/AwEPEzQO7P8
package main
import (
"fmt"
"math"
"math/rand"
)
func main() {
var buckets [20]int
for i := 0; i < 1000; i++ {
r := int(math.Abs(rand.NormFloat64())*10) % 20
buckets[r]++
}
fmt.Println(buckets)
}
示例输出:
[86 92 76 80 73 69 60 69 58 51 47 38 44 30 29 24 19 27 18 10]
不过这是随机的,所以你仍然可能得到全部末尾项...
如果你想要一个步进函数,其中前半部分的数字是后半部分的10倍,只需使用两个随机数。
n := rand.Intn(10)
if rand.Float64() < 0.1 {
n = n + 10
}
在Go Playground上查看示例:https://go.dev/play/p/CitUsHmwQez
package main
import (
"fmt"
"math/rand"
)
func main() {
var buckets [20]int
for i := 0; i < 1000; i++ {
r := rand.Intn(10)
if rand.Float64() < 0.1 {
r = r + 10
}
buckets[r]++
}
fmt.Println(buckets)
}
示例输出:
[96 92 89 89 88 78 95 86 83 98 15 10 15 10 10 12 4 11 11 8]
英文:
Assuming you're happy with the normal distribution, you can use rand.Normfloat64(). If your array has 20 items:
int(math.Abs(rand.NormFloat64())*10) % 20
Will produce numbers that are weighted toward the start of the list. And
20 - int(math.Abs(rand.NormFloat64())*10) % 20
Will produce numbers that are weighted toward the end of the list.
Here's an example that demonstrates a sample random distribution.
On go playground: https://go.dev/play/p/AwEPEzQO7P8
package main
import (
"fmt"
"math"
"math/rand"
)
func main() {
var buckets [20]int
for i := 0; i < 1000; i++ {
r := int(math.Abs(rand.NormFloat64())*10) % 20
buckets[r]++
}
fmt.Println(buckets)
}
Sample output:
[86 92 76 80 73 69 60 69 58 51 47 38 44 30 29 24 19 27 18 10]
It's random though, so you could still get all tail end items ....
If you want a step function where the numbers of the first half are 10x the numbers of the left, just use two rands.
n := rand.Intn(10)
if rand.Float64() < 0.1 {
n = n + 10
}
Example on go playground: https://go.dev/play/p/CitUsHmwQez
package main
import (
"fmt"
"math/rand"
)
func main() {
var buckets [20]int
for i := 0; i < 1000; i++ {
r := rand.Intn(10)
if rand.Float64() < 0.1 {
r = r + 10
}
buckets[r]++
}
fmt.Println(buckets)
}
Sample output
[96 92 89 89 88 78 95 86 83 98 15 10 15 10 10 12 4 11 11 8]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论