random choice 随机选择问题
版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc
1. 前言
工作中有一个场景是,我们要从可以用的N台机器中,随机选出M台机器,
当时因为时间有限,我实现不是优雅,且性能上,估计也会差点。今天晚上有空重新对这个问题进行了思考
2. 分析
提到这个问题,我们很容易联想到排列组合中,从袋子中摸球的问题。
袋子中有N个球,编号分别是0 ~ N -1,    每次从袋子中取出一个球(不放回),共取出M次。
在实际工作中,可能会很多类似的场景
- 从N个汽车型号中随机选出M个
- 从N个候选人中选出M个
在随机选择的过程中,我们不一定要直接操作这些实体(汽车,候选人),只用对它们所对应的编号进行操作即可
3. 结果
基于2. 中的分析,我实现了代码,并封装成了库,有兴趣的朋友可以看看
传送门:randomchoice
Quick Start
package main
import (
    rc "github.com/vearne/randomchoice"
    "fmt"
)
type Car struct{
    color string
    name  string
}
func (c *Car) String() string{
    return c.color + "-" + c.name
}
func main(){
    // example 1
    var children []string
    children = []string{"lily", "rose","lisa"}
    // randomly select 2 kids from children
    idxSlice := rc.RandomChoice(len(children), 2)
    result := make([]string, 0, 2)
    for _, v := range idxSlice{
        result = append(result, children[v])
    }
    // result: selected kids
    fmt.Println(result)
    // example 2
    var carSlice []*Car= make([]*Car, 0, 3)
    bmw := Car{color:"black", name:"bmw"}
    carSlice = append(carSlice, &bmw)
    buick := Car{color:"silvery", name:"buick"}
    carSlice = append(carSlice, &buick )
    skoda := Car{color:"white", name:"skoda"}
    carSlice = append(carSlice, &skoda )
    // random select 2 kinds from carSlice
    idxSlice = rc.RandomChoice(len(carSlice), 2)
    cars := make([]*Car, 0, 2)
    for _, v := range idxSlice{
        cars = append(cars, carSlice[v])
    }
    fmt.Println(cars)
}
性能指标
测试环境
CPU Model Name: 2.3 GHz Intel Core i5
CPU Processors: 4
Memory: 8GB
Test Results
| N(数组长度) | M(希望选出的个数) | ns/op | ops(operation per second) | 
|---|---|---|---|
| 10 | 3 | 135 | 740w | 
| 100 | 3 | 267 | 370w | 
| 1000 | 3 | 1502 | 66w | 
| 10 | 5 | 197 | 507w | 
| 100 | 5 | 336 | 297w | 
| 1000 | 5 | 1582 | 63w | 
后记
后来笔者在阅读NSQ源码时,发现它的随机选择函数实现的也有性能问题,最终笔者的pull request 被采纳
链接地址
有兴趣的看一下
请我喝瓶饮料
