在Go模板中随机选择内容。

huangapple go评论87阅读模式
英文:

Choose content randomly in Go templates

问题

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

{{prob 50}}
    这将以50%的概率出现。
{{prob 30}}
    这将以30%的概率出现。
{{prob 20}}
    你明白了吧。
{{endprob}}

到目前为止,我想到的最好的方法是:

{{choose . "template1" 50 "template2" 30 "template3" 20}}

其中choose是属于FuncMap的函数。当前模板被传递给自身,例如.T,而templateN是相关的模板。该函数将选择模板,在.T中查找并使用.进行渲染。另一个类似的选项是直接将templateN作为.的一部分传递。

我想知道是否有更优雅/不那么hackish的方法?我猜,在text/template中创建自定义操作是不可能的,对吗?

英文:

I would like to choose a part of the generated document randomly based on the given weights, something like this pseudo-code:

{{prob 50}}
    This will appear with probability 50%.
{{prob 30}}
    This will appear with probability 30%.
{{prob 20}}
     You got the idea.
{{endprob}}

The best things that has come to my mind so far is:

{{choose . "template1" 50 "template2" 30 "template3" 20}}

where choose is my function that belongs to FuncMap. The current template is passed to itself as e.g. .T and templateN are the associated templates. The function would choose the template, look it up in .T and render with .. Another similar option would be to pass templateN as part of . directly.

I wonder if there's a more elegant / less hackish way? I guess, it's not possible to create custom actions in text/template, is it?

答案1

得分: 3

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

您可以通过使用函数映射和内置的{{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}}`))

[kbd][playground](http://play.golang.org/p/c_4SryGkL8)[/kbd]

这是另一种允许您在模板中指定权重而不是范围的替代方法:

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

[kbd][playground](http://play.golang.org/p/oGbawWH4Xg)[/kbd]

<details>
<summary>英文:</summary>

The standard template packages do not support custom actions.

You can get close to your proposed `{{prob}}/{{endprob}}` action using a function map and the built-in `{{if}}` action.

Convert the weights to non-overlapping ranges in [0.0,1.0). Use a random number in [0.0,1.0) to select an alternative using an if action in the template.

    var t = template.Must(template.New(&quot;&quot;).
	    Funcs(template.FuncMap{&quot;rand&quot;: 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}}`))

&lt;kbd&gt;[playground](http://play.golang.org/p/c_4SryGkL8)&lt;/kbd&gt;

Here&#39;s an alternative that allows you to specify weights in the template instead of ranges:

    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 &lt;= rp.n
    }

    func newRandPicker() *randPicker {
        return &amp;randPicker{n: rand.Float64()}
    }

    var t = template.Must(template.New(&quot;&quot;).
        Funcs(template.FuncMap{&quot;rp&quot;: 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}}`))

&lt;kbd&gt;[playground](http://play.golang.org/p/oGbawWH4Xg)&lt;/kbd&gt;


</details>



huangapple
  • 本文由 发表于 2014年10月6日 19:29:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/26215287.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定