英文:
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'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'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 (
"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, "")
}
// if you use some funcs everywhere have some package export a Template constructor that makes them available, like this:
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() {
// test 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
}
}
[Here's a variation](http://play.golang.org/p/MWpr9mlTdC) that also exports "conjoin", and an "isLast" 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>
这个团队的成员是Bob、Jane和Mike。
</pre>
当列表中只有一个元素时,你的单数示例是什么?例如,
<pre>
这个团队唯一的成员是Bob。
</pre>
当列表中没有元素时,你的空示例是什么?例如,
<pre>
这个团队没有成员。
</pre>
从邮件合并中创建正确的英文句子和段落是困难的。
<details>
<summary>英文:</summary>
For the "creation of a proper English formatted sentence" from a list use a function.
Your plural example is
<pre>
The members of this team are Bob, Jane, and Mike.
</pre>
What is your singular example where there is only one element in the list? For example,
<pre>
The only member of this team is Bob.
</pre>
What is your empty example when there are no elements in the list? For example,
<pre>
There are no members of this team.
</pre>
Creating proper English sentences and paragraphs from a mail merge is hard.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论