2014-10-06 57 views
2

我想選擇隨機基於給定的權重生成的文檔的一部分,像這樣的僞代碼:隨機選擇內容轉到模板

{{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作爲.的一部分。

我不知道是否有更優雅/少hackish的方式?我猜想,在text/template中無法創建自定義操作,是嗎?

回答

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

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

+0

是啊,這肯定是一個選項,只是想讓它更有用處R-友好。 – bereal 2014-10-06 17:42:38

+0

真的好主意,謝謝! – bereal 2014-10-06 18:28:30