我想根据给定的权重随机选择生成文档的一部分,类似于这个伪代码:
{{prob 50}}
This will appear with probability 50%.
{{prob 30}}
This will appear with probability 30%.
{{prob 20}}
You got the idea.
{{endprob}}
到目前为止,我想到的最好的事情是:
{{choose . "template1" 50 "template2" 30 "template3" 20}}
其中choose
是属于FuncMap
的函数。当前模板作为例如传递给它自己。 .T
和templateN
是关联的模板。该函数将选择模板,在.T
中查找并使用.
进行渲染。另一个类似的选择是直接将templateN
作为.
的一部分传递。
我想知道是否有更优雅/更少的hackish方式?我想,在text/template
中无法创建自定义操作,是吗?
答案 0 :(得分:3)
标准模板包不支持自定义操作。
您可以使用功能映射和内置{{prob}}/{{endprob}}
操作来接近建议的{{if}}
操作。
将权重转换为[0.0,1.0]中的非重叠范围。使用[0.0,1.0]中的随机数在模板中使用if动作选择替代方案。
var t = template.Must(template.New("").
Funcs(template.FuncMap{"rand": rand.Float64}).
Parse(`
{{$r := rand}}
{{if le $r 0.5}}
This will appear with probability 50%.
{{else if le $r 0.8}}
This will appear with probability 30%.
{{else}}
You got the idea.
{{end}}`))
这是一个替代方案,允许您在模板中指定权重而不是范围:
type randPicker struct {
n float64 // random number in [0.0,1.0)
t float64 // total of weights so far
}
func (rp *randPicker) Weight(w float64) bool {
rp.t += w
return rp.t <= rp.n
}
func newRandPicker() *randPicker {
return &randPicker{n: rand.Float64()}
}
var t = template.Must(template.New("").
Funcs(template.FuncMap{"rp": newRandPicker}).
Parse(`
{{$rp := rp}}
{{if rp.Weight 0.50}}
This will appear with probability 50%.
{{else if rp.Weight 0.30}}
This will appear with probability 30%.
{{else}}
You got the idea
{{end}}`))