使用Golang模板打印以逗号和“或”分隔的列表。

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

Use golang template to print list separated with comma and "or"

问题

在stackoverflow上已经讨论过如何打印以逗号分隔的列表,代码如下:

{{ range $index, $element := .TeamMembers}}
    {{if $index}},{{end}}
    {{$element.Name}}
{{end}}

当你需要一个不同于最后一项的列表分隔符(例如使用"或"),是否有一个简单的解决方案:

{name}, {name}, {name}, or {name}

这样可以创建格式化的句子,例如:

这个团队的成员是Bob,Jane和Mike。

我可以提供一些模板代码,但可能会变得非常冗长和复杂。

英文:

It is already elsewhere discussed on stackoverflow that you can print a list separated by comma, as follows:

{{ range $index, $element := .TeamMembers}}
    {{if $index}},{{end}}
    {{$element.Name}}
{{end}}

Is there an easy solution for when you need a list separator that is different for the last item, to include an "or":

{name}, {name}, {name}, or {name}

This is to allow, for example, creation of formatted sentences such as:

The members of this team are Bob, Jane, and Mike.

Any template code I can workout ends up extremely verbose and complicated.

答案1

得分: 4

在你的模板中导出一个函数

text/template,就像其他一些模板系统一样,并不试图直接用于编程;它只是提供了一种更好的方式来将数据和函数与标记结合起来,当它不足以满足需求时,你需要编写其他的展示代码。你可以编写一个yourapp/template模块,导出一个调用Funcs()New()版本,以添加你使用的常用函数。

(你可能会发现除了这些函数之外还有很多其他的函数用途;例如,Django提供了很多内置函数,用于复数形式、格式化、国际化等等,人们经常扩展这个集合。)

package main // package mytemplate

import (
	"fmt"
	"os"
	"strings"
	"text/template"
)

func conjoin(conj string, items []string) string {
	if len(items) == 0 {
		return ""
	}
	if len(items) == 1 {
		return items[0]
	}
	if len(items) == 2 { // "a and b" not "a, and b"
		return items[0] + " " + conj + " " + items[1]
	}

	sep := ", "
	pieces := []string{items[0]}
	for _, item := range items[1 : len(items)-1] {
		pieces = append(pieces, sep, item)
	}
	pieces = append(pieces, sep, conj, " ", items[len(items)-1])

	return strings.Join(pieces, "")
}

// 如果你在很多地方都使用了一些函数,可以有一些包导出一个模板构造函数,使它们可用,就像这样:

var commonFuncs = template.FuncMap{
	"andlist": func(items []string) string { return conjoin("and", items) },
	"orlist":  func(items []string) string { return conjoin("or", items) },
}

func New(name string) *template.Template {
	return template.New(name).Funcs(commonFuncs)
}

func main() {
	// 测试 conjoin
	fmt.Println(conjoin("or", []string{}))
	fmt.Println(conjoin("or", []string{"Bob"}))
	fmt.Println(conjoin("or", []string{"Bob", "Mike"}))
	fmt.Println(conjoin("or", []string{"Bob", "Mike", "Harold"}))

	people := []string{"Bob", "Mike", "Harold", "Academy Award nominee William H. Macy"}
	data := map[string]interface{}{"people": people}
	tmpl, err := New("myyy template").Parse("{{ orlist .people }} / {{ andlist .people }}")
	if err != nil {
		fmt.Println("sadness:", err.Error())
		return
	}
	err = tmpl.Execute(os.Stdout, data)
	if err != nil {
		fmt.Println("sadness:", err.Error())
		return
	}
}

[这里是一个变体](http://play.golang.org/p/MWpr9mlTdC),它还导出了"conjoin"和"isLast"函数,你可以在一种冗长的构造中使用"isLast"函数,在循环的最后一次中以某种特殊方式执行一些任意操作。

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

[Export a function to your template](http://play.golang.org/p/QMy-pkj2N8). 

`text/template`, like some other template systems, doesn&#39;t try be good for programming in directly; it just provides a better way to stitch your data and functions with your markup, and you need to write other presentational code when it&#39;s insufficient. You can write a `yourapp/template` module that exports a version of `New()` that calls `Funcs()` to add the common functions you use. 

(You might find uses for a lot more functions than just these; Django, for example, offers [lots of builtins](https://docs.djangoproject.com/en/1.7/ref/templates/builtins/) for pluralization, formatting, i18n, etc., and folks still often extend the set.)

    package main // package mytemplate
    
    import (
    	&quot;fmt&quot;
    	&quot;os&quot;
    	&quot;strings&quot;
    	&quot;text/template&quot;
    )
    
    func conjoin(conj string, items []string) string {
    	if len(items) == 0 {
    		return &quot;&quot;
    	}
    	if len(items) == 1 {
    		return items[0]
    	}
    	if len(items) == 2 { // &quot;a and b&quot; not &quot;a, and b&quot;
    		return items[0] + &quot; &quot; + conj + &quot; &quot; + items[1]
    	}
    
    	sep := &quot;, &quot;
    	pieces := []string{items[0]}
    	for _, item := range items[1 : len(items)-1] {
    		pieces = append(pieces, sep, item)
    	}
    	pieces = append(pieces, sep, conj, &quot; &quot;, items[len(items)-1])
    
    	return strings.Join(pieces, &quot;&quot;)
    }
    
    // if you use some funcs everywhere have some package export a Template constructor that makes them available, like this:
    
    var commonFuncs = template.FuncMap{
    	&quot;andlist&quot;: func(items []string) string { return conjoin(&quot;and&quot;, items) },
    	&quot;orlist&quot;:  func(items []string) string { return conjoin(&quot;or&quot;, items) },
    }
    
    func New(name string) *template.Template {
    	return template.New(name).Funcs(commonFuncs)
    }
    
    func main() {
    	// test conjoin
    	fmt.Println(conjoin(&quot;or&quot;, []string{}))
    	fmt.Println(conjoin(&quot;or&quot;, []string{&quot;Bob&quot;}))
    	fmt.Println(conjoin(&quot;or&quot;, []string{&quot;Bob&quot;, &quot;Mike&quot;}))
    	fmt.Println(conjoin(&quot;or&quot;, []string{&quot;Bob&quot;, &quot;Mike&quot;, &quot;Harold&quot;}))
    
    	people := []string{&quot;Bob&quot;, &quot;Mike&quot;, &quot;Harold&quot;, &quot;Academy Award nominee William H. Macy&quot;}
    	data := map[string]interface{}{&quot;people&quot;: people}
    	tmpl, err := New(&quot;myyy template&quot;).Parse(&quot;{{ orlist .people }} / {{ andlist .people }}&quot;)
    	if err != nil {
    		fmt.Println(&quot;sadness:&quot;, err.Error())
    		return
    	}
    	err = tmpl.Execute(os.Stdout, data)
    	if err != nil {
    		fmt.Println(&quot;sadness:&quot;, err.Error())
    		return
    	}
    }

[Here&#39;s a variation](http://play.golang.org/p/MWpr9mlTdC) that also exports &quot;conjoin&quot;, and an &quot;isLast&quot; function you can use in a kind of verbose construction to do some arbitrary thing differently in the last go through the loop.

</details>



# 答案2
**得分**: 1

对于从列表中创建正确的英文格式句子的问题可以使用一个函数

你的复数示例是

<pre>
这个团队的成员是BobJane和Mike
</pre>

当列表中只有一个元素时你的单数示例是什么例如

<pre>
这个团队唯一的成员是Bob
</pre>

当列表中没有元素时你的空示例是什么例如

<pre>
这个团队没有成员
</pre>

从邮件合并中创建正确的英文句子和段落是困难的

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

For the &quot;creation of a proper English formatted sentence&quot; from a list use a function.

Your plural example is

&lt;pre&gt;
The members of this team are Bob, Jane, and Mike.
&lt;/pre&gt;

What is your singular example where there is only one element in the list? For example,

&lt;pre&gt;
The only member of this team is Bob.
&lt;/pre&gt;

What is your empty example when there are no elements in the list? For example,

&lt;pre&gt;
There are no members of this team.
&lt;/pre&gt;

Creating proper English sentences and paragraphs from a mail merge is hard. 

</details>



huangapple
  • 本文由 发表于 2014年11月13日 07:11:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/26898446.html
匿名

发表评论

匿名网友

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

确定