在Go中随机化MongoDB查询的顺序

时间:2017-04-01 13:10:05

标签: mongodb go random slice mgo

这是我的问题:

c := session.DB("searchV").C("video")
var results []BadVideo
err5 := c.Find(nil).All(&results)
fmt.Println("request done")
if err5 != nil {
    panic(err5)
}
var i = 0
for _,badvideo := range results {
}

我想随机化浏览查询项目的顺序,以便对请求的每个项目进行操作......

因此,每次运行时,我都会以不同的顺序浏览它。

1 个答案:

答案 0 :(得分:1)

手动改组

这是一个简单的随机播放算法,可以对[]BadVido切片进行随机化(随机化):

func shuffle(r []BadVideo) {
    for i := len(r) - 1; i > 0; i-- {
        j := rand.Intn(i + 1)
        r[i], r[j] = r[j], r[i]
    }
}

因此,在您加载结果后,只需在其上调用shuffle(results)即可。

为了进行测试,我将使用简单的BadVideo类型:

type BadVideo struct {
    Name string
}

func main() {
    rand.Seed(time.Now().UnixNano())
    results := []BadVideo{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
    shuffle(results)
    fmt.Println(results)
}

输出(在Go Playground上尝试):

[{c} {d} {b} {e} {a}]

工作原理:

要对切片进行混洗,shuffle()函数会从切片中为每个索引随机选择一个元素。它就像向下迭代所有元素一样,并从剩余的切片中选择一个随机元素(包括我们当前正在选择的元素的索引,因为随机顺序还包括一个元素"保持原样的位置&# 34;),并使用随机索引将元素与所选的随机索引交换。循环一直持续到i > 0(而不是直到i >=0),因为如果只剩下1个元素,则不需要将它与自身交换。

使用rand.Perm()

shuffle()的另一种变体可以利用rand.Perm()来返回包含混洗数字的切片。我们可以使用这些随机数来说明如何重新排序结果:

func shuffle(r []BadVideo) {
    r2 := append([]BadVideo(nil), r...)
    for i, j := range rand.Perm(len(r)) {
        r[i] = r2[j]
    }
}

Go Playground上尝试此变体。

有一点需要注意:在我们进行重新排序之前,我们必须保存原始切片(复制它),这样我们就可以在切片中写入结果时选择随机索引指定的原始元素。我通过将完整切片附加到nil切片来创建副本。