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 被采纳
链接地址
有兴趣的看一下