Go 戈朗未更换样品

Go 戈朗未更换样品,go,random,slice,sampling,Go,Random,Slice,Sampling,在golang,不更换切片的最佳取样方式是什么 a := make([]int, 100) for i := range a { a[i] = i } # TODO sample 5 elements from a without replacement. 如果集合大小总体上相对较小,或者您正在对集合的大部分进行采样,最简单的方法是对元素进行无序排列,然后选择第一个n: rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j],

在golang,不更换切片的最佳取样方式是什么

a := make([]int, 100)
for i := range a {
    a[i] = i
}

# TODO sample 5 elements from a without replacement.

如果集合大小总体上相对较小,或者您正在对集合的大部分进行采样,最简单的方法是对元素进行无序排列,然后选择第一个
n

rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
fmt.Println(a[:5])

如果您不想洗牌整个集合,但改变集合的顺序(或复制整个集合)是可以接受的,那么您可以通过从切片中删除使用的值来更有效地“记录”使用的值

// create a copy of the slice header
c := a
samples := make([]int, n)

for i := 0; i < n; i++ {
    r := int(rand.Int63n(int64(len(c))))
    samples[i] = c[r]

    // remove the sample from the copy slice
    c[r], c[len(c)-1] = c[len(c)-1], c[r]
    c = c[:len(c)-1]
}
//创建切片头的副本
c:=a
样本:=制造([]整数,n)
对于i:=0;i
如果集合的大小相当大,并且只对一小部分进行采样,则可以通过记录样本索引而不重复它,从原始集合中进行采样,而无需修改。显然,随着样本大小与集合大小之比的增加,碰撞的数量将增加,从而降低效率

例如:

// record indexes here to prevent duplicates
indexes := make(map[int]bool)

// create n random indexes
for i := 0; i < n; i++ {
    var r int
    for {
        r = int(rand.Int63n(int64(len(a))))
        if indexes[r] {
            continue
        }
        break
    }

    indexes[r] = true
}

samples := make([]int, 0, n)
for i := range indexes {
    samples = append(samples, a[i])
}
//在此处记录索引以防止重复
索引:=make(映射[int]bool)
//创建n个随机索引
对于i:=0;i
如果集合的总体大小相对较小,或者您正在对集合的很大一部分进行采样,最简单的方法是将元素混洗,然后选择第一个
n

rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
fmt.Println(a[:5])

如果您不想洗牌整个集合,但改变集合的顺序(或复制整个集合)是可以接受的,那么您可以通过从切片中删除使用的值来更有效地“记录”使用的值

// create a copy of the slice header
c := a
samples := make([]int, n)

for i := 0; i < n; i++ {
    r := int(rand.Int63n(int64(len(c))))
    samples[i] = c[r]

    // remove the sample from the copy slice
    c[r], c[len(c)-1] = c[len(c)-1], c[r]
    c = c[:len(c)-1]
}
//创建切片头的副本
c:=a
样本:=制造([]整数,n)
对于i:=0;i
如果集合的大小相当大,并且只对一小部分进行采样,则可以通过记录样本索引而不重复它,从原始集合中进行采样,而无需修改。显然,随着样本大小与集合大小之比的增加,碰撞的数量将增加,从而降低效率

例如:

// record indexes here to prevent duplicates
indexes := make(map[int]bool)

// create n random indexes
for i := 0; i < n; i++ {
    var r int
    for {
        r = int(rand.Int63n(int64(len(a))))
        if indexes[r] {
            continue
        }
        break
    }

    indexes[r] = true
}

samples := make([]int, 0, n)
for i := range indexes {
    samples = append(samples, a[i])
}
//在此处记录索引以防止重复
索引:=make(映射[int]bool)
//创建n个随机索引
对于i:=0;i
根据样本需要的随机性,我可能会将元素复制到一个
映射[T]结构{}
(其中
T
是结果类型)和
范围
中,以获得我的结果

// assume input is []int
res := make([]int, len(input))
desorted := make(map[int]struct{})

for _, v := range input {
        desorted[v] = struct{}
}

i := 0
for k, _ := range desorted {
        res[i] = k
        i++
}

根据样本需要的随机性,我可能会将元素复制到一个
map[T]struct{}
(其中
T
是结果类型)和
range
,以获得我的结果

// assume input is []int
res := make([]int, len(input))
desorted := make(map[int]struct{})

for _, v := range input {
        desorted[v] = struct{}
}

i := 0
for k, _ := range desorted {
        res[i] = k
        i++
}

这将修改原始数组,我假设“不替换”意味着原始数组不会被修改。您需要先复制一份。@Zak:“不替换”只意味着同一元素不会被多次采样。不很好地修改原始切片可能是另一个要求,但这里没有指定。好的,很好。TIL@JimB奥巴马对“不替换”的定义是正确的。但是,当a很大时,此解决方案的计算成本很高。@alpaca:您的示例并不大,这使它成为一个合适的解决方案。否则,您可以从原始集合中删除随机样本,或者如果不想修改集合,只需记录样本索引,不重复它们。这将修改原始数组,我假设“不替换”意味着原始数组不会被修改。您需要先复制一份。@Zak:“不替换”只意味着同一元素不会被多次采样。不很好地修改原始切片可能是另一个要求,但这里没有指定。好的,很好。TIL@JimB奥巴马对“不替换”的定义是正确的。但是,当a很大时,此解决方案的计算成本很高。@alpaca:您的示例并不大,这使它成为一个合适的解决方案。否则,您可以从原始集合中删除随机样本,或者如果不想修改集合,只需记录样本索引,而不重复它们。