【问题标题】:Choose content randomly in Go templates在 Go 模板中随机选择内容
【发布时间】:2023-03-18 18:39:01
【问题描述】:

我想根据给定的权重随机选择生成文档的一部分,类似于以下伪代码:

{{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 的函数。当前模板被传递给自身,例如.TtemplateN 是关联的模板。该函数将选择模板,在.T 中查找并使用. 进行渲染。另一个类似的选择是将templateN 作为. 的一部分直接传递。

我想知道是否有更优雅/不那么骇人听闻的方式?我想,不可能在text/template 中创建自定义操作,是吗?

【问题讨论】:

    标签: templates go


    【解决方案1】:

    标准模板包不支持自定义操作。

    您可以使用函数映射和内置的{{if}} 操作来接近您提议的{{prob}}/{{endprob}} 操作。

    将权重转换为 [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}}`))
    

    playground

    这是一种替代方法,可让您在模板中指定权重而不是范围:

    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}}`))
    

    playground

    【讨论】:

    • 是的,这绝对是一个选择,只是想让它更加用户友好。
    猜你喜欢
    • 2018-09-02
    • 2016-03-03
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2019-07-30
    • 1970-01-01
    相关资源
    最近更新 更多