Fork me on GitHub

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | 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 被采纳
链接地址
有兴趣的看一下


请我喝瓶饮料

微信支付码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据