目标:每次生成块时从列表中选择一个随机数
Python 代码示例使其更清晰。
我有这个清单:
listbytes = [87, 88, 89, 90]
还有这个分割数据的函数:
def chunks(lst, n):
"Yield successive chunks from lst, where n is a list of possible sizes"
i = 0
while i < len(lst):
k = min(random.choice(n), len(lst) - i)
yield lst[i:i + k]
i += k
我这样称呼它:
for chunk in chunks(d, listbytes):
......
创建的每个块都有一个从 87 到 90 的随机大小,所以: 1 个块的大小可能为 87,下一个块的大小可能为 90,依此类推..
我在 Go 中有一个类似的函数来分割数据:
func split(buf []byte, lim int) [][]byte {
var chunk []byte
chunks := make([][]byte, 0, len(buf)/lim+1)
for len(buf) >= lim {
chunk, buf = buf[:lim], buf[lim:]
chunks = append(chunks, chunk)
}
if len(buf) > 0 {
chunks = append(chunks, buf[:len(buf)])
}
return chunks
}
这和python中的区别在于数据是使用固定数字分块的。示例:
for _, chunk := range split(buf[:n], 100) {
.......
这会将数据分块固定大小为 100,因此每个块的大小为 100,而 Python 的大小为 87 到 90。
所需的输出是一样的:块每次都应该有一个随机大小。
我怎样才能实现相同的目标但在运行中?
答案 0 :(得分:3)
我认为这是你的 Python 程序的 Go 版本(有一些 main 来运行它):
package main
import (
"fmt"
"math/rand"
"time"
)
// split breaks buf into a slice of slices whose lengths
// are randomly chosen from sizes, except for the last slice.
// The last slice's length is less than or equal to a size that
// was chosen from sizes, but may be larger than some other size
// found in sizes.
func split(r *rand.Rand, buf []byte, sizes []int) [][]byte {
var chunk []byte
chunks := make([][]byte, 0)
for len(buf) > 0 {
sz := sizes[r.Intn(len(sizes))]
if sz > len(buf) {
sz = len(buf)
}
chunk, buf = buf[:sz], buf[sz:]
chunks = append(chunks, chunk)
}
return chunks
}
func main() {
// Go's RNG is deterministic unless seeded with current time.
s := int64(time.Now().Nanosecond())
r := rand.New(rand.NewSource(s))
sizes := []int{2,3,5,7}
buf := []byte{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25}
fmt.Printf("result=%v\n", split(r, buf, sizes))
}
这是相同的 Go 游乐场链接(因此您可以轻松查看和运行): https://play.golang.org/p/U1vkPAKOQmI (请注意,Go Playground 的时间总是相同的,因此它始终运行相同)。
答案 1 :(得分:2)
基于 io.Reader
的解决方案
main_test.go
package main
import (
"bytes"
"fmt"
"io"
"math/rand"
"strings"
"time"
)
type rndReader struct {
R io.Reader
Rnd interface{ Intn(n int) int }
buf []byte
lastErr error
}
func (r *rndReader) Read(p []byte) (n int, err error) {
if r.Rnd == nil {
r.Rnd = rand.New(rand.NewSource(time.Now().Unix()))
}
if r.lastErr != nil && len(r.buf) < 1 {
return 0, r.lastErr
}
// rather than a function argument (n), take len(p)
j := len(p)
if r.lastErr == nil {
n, err = r.R.Read(p) // read to p
r.buf = append(r.buf, p[:n]...) // save the read
r.lastErr = err
}
p = p[:0] // reset p, prepare it to receive the random chunk
k := min(r.Rnd.Intn(j), len(r.buf)) // select a random k
p = append(p, r.buf[:k]...) // copy the desired portion from the internal buf to p
copy(r.buf, r.buf[k:]) // re arrange the internal buffer
r.buf = r.buf[:len(r.buf)-k] // adjust its len.
return len(p), nil
}
func min(n, k int) int {
if n > k {
return k
}
return n
}
func ExampleFromStrings() {
in := strings.Repeat(`12345`, 4)
s := strings.NewReader(in)
r := rndReader{R: s, Rnd: rand.New(rand.NewSource(1))}
out := make([]byte, 3)
for {
n, err := r.Read(out)
if err != nil {
break
}
fmt.Printf(`n=%v err=%v buf="%s"`+"\n", n, err, out[:n])
}
// Output:
// n=2 err=<nil> buf="12"
// n=0 err=<nil> buf=""
// n=2 err=<nil> buf="34"
// n=2 err=<nil> buf="51"
// n=1 err=<nil> buf="2"
// n=0 err=<nil> buf=""
// n=1 err=<nil> buf="3"
// n=2 err=<nil> buf="45"
// n=1 err=<nil> buf="1"
// n=0 err=<nil> buf=""
// n=2 err=<nil> buf="23"
// n=1 err=<nil> buf="4"
// n=0 err=<nil> buf=""
// n=2 err=<nil> buf="51"
// n=1 err=<nil> buf="2"
// n=2 err=<nil> buf="34"
// n=0 err=<nil> buf=""
// n=1 err=<nil> buf="5"
}
func ExampleFromBytes() {
in := []byte(strings.Repeat(`12345`, 4))
s := bytes.NewBuffer(in)
r := rndReader{R: s, Rnd: rand.New(rand.NewSource(1))}
out := make([]byte, 3)
for {
n, err := r.Read(out)
if err != nil {
break
}
fmt.Printf(`n=%v err=%v buf="%s"`+"\n", n, err, out[:n])
}
// Output:
// n=2 err=<nil> buf="12"
// n=0 err=<nil> buf=""
// n=2 err=<nil> buf="34"
// n=2 err=<nil> buf="51"
// n=1 err=<nil> buf="2"
// n=0 err=<nil> buf=""
// n=1 err=<nil> buf="3"
// n=2 err=<nil> buf="45"
// n=1 err=<nil> buf="1"
// n=0 err=<nil> buf=""
// n=2 err=<nil> buf="23"
// n=1 err=<nil> buf="4"
// n=0 err=<nil> buf=""
// n=2 err=<nil> buf="51"
// n=1 err=<nil> buf="2"
// n=2 err=<nil> buf="34"
// n=0 err=<nil> buf=""
// n=1 err=<nil> buf="5"
}
func main() {}