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

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

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

问题

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

  1. {{ range $index, $element := .TeamMembers}}
  2. {{if $index}},{{end}}
  3. {{$element.Name}}
  4. {{end}}

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

  1. {name}, {name}, {name}, or {name}

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

  1. 这个团队的成员是BobJaneMike

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

英文:

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

  1. {{ range $index, $element := .TeamMembers}}
  2. {{if $index}},{{end}}
  3. {{$element.Name}}
  4. {{end}}

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

  1. {name}, {name}, {name}, or {name}

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

  1. 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提供了很多内置函数,用于复数形式、格式化、国际化等等,人们经常扩展这个集合。)

  1. package main // package mytemplate
  2. import (
  3. "fmt"
  4. "os"
  5. "strings"
  6. "text/template"
  7. )
  8. func conjoin(conj string, items []string) string {
  9. if len(items) == 0 {
  10. return ""
  11. }
  12. if len(items) == 1 {
  13. return items[0]
  14. }
  15. if len(items) == 2 { // "a and b" not "a, and b"
  16. return items[0] + " " + conj + " " + items[1]
  17. }
  18. sep := ", "
  19. pieces := []string{items[0]}
  20. for _, item := range items[1 : len(items)-1] {
  21. pieces = append(pieces, sep, item)
  22. }
  23. pieces = append(pieces, sep, conj, " ", items[len(items)-1])
  24. return strings.Join(pieces, "")
  25. }
  26. // 如果你在很多地方都使用了一些函数,可以有一些包导出一个模板构造函数,使它们可用,就像这样:
  27. var commonFuncs = template.FuncMap{
  28. "andlist": func(items []string) string { return conjoin("and", items) },
  29. "orlist": func(items []string) string { return conjoin("or", items) },
  30. }
  31. func New(name string) *template.Template {
  32. return template.New(name).Funcs(commonFuncs)
  33. }
  34. func main() {
  35. // 测试 conjoin
  36. fmt.Println(conjoin("or", []string{}))
  37. fmt.Println(conjoin("or", []string{"Bob"}))
  38. fmt.Println(conjoin("or", []string{"Bob", "Mike"}))
  39. fmt.Println(conjoin("or", []string{"Bob", "Mike", "Harold"}))
  40. people := []string{"Bob", "Mike", "Harold", "Academy Award nominee William H. Macy"}
  41. data := map[string]interface{}{"people": people}
  42. tmpl, err := New("myyy template").Parse("{{ orlist .people }} / {{ andlist .people }}")
  43. if err != nil {
  44. fmt.Println("sadness:", err.Error())
  45. return
  46. }
  47. err = tmpl.Execute(os.Stdout, data)
  48. if err != nil {
  49. fmt.Println("sadness:", err.Error())
  50. return
  51. }
  52. }
  53. [这里是一个变体](http://play.golang.org/p/MWpr9mlTdC),它还导出了"conjoin"和"isLast"函数,你可以在一种冗长的构造中使用"isLast"函数,在循环的最后一次中以某种特殊方式执行一些任意操作。
  54. <details>
  55. <summary>英文:</summary>
  56. [Export a function to your template](http://play.golang.org/p/QMy-pkj2N8).
  57. `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.
  58. (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.)
  59. package main // package mytemplate
  60. import (
  61. &quot;fmt&quot;
  62. &quot;os&quot;
  63. &quot;strings&quot;
  64. &quot;text/template&quot;
  65. )
  66. func conjoin(conj string, items []string) string {
  67. if len(items) == 0 {
  68. return &quot;&quot;
  69. }
  70. if len(items) == 1 {
  71. return items[0]
  72. }
  73. if len(items) == 2 { // &quot;a and b&quot; not &quot;a, and b&quot;
  74. return items[0] + &quot; &quot; + conj + &quot; &quot; + items[1]
  75. }
  76. sep := &quot;, &quot;
  77. pieces := []string{items[0]}
  78. for _, item := range items[1 : len(items)-1] {
  79. pieces = append(pieces, sep, item)
  80. }
  81. pieces = append(pieces, sep, conj, &quot; &quot;, items[len(items)-1])
  82. return strings.Join(pieces, &quot;&quot;)
  83. }
  84. // if you use some funcs everywhere have some package export a Template constructor that makes them available, like this:
  85. var commonFuncs = template.FuncMap{
  86. &quot;andlist&quot;: func(items []string) string { return conjoin(&quot;and&quot;, items) },
  87. &quot;orlist&quot;: func(items []string) string { return conjoin(&quot;or&quot;, items) },
  88. }
  89. func New(name string) *template.Template {
  90. return template.New(name).Funcs(commonFuncs)
  91. }
  92. func main() {
  93. // test conjoin
  94. fmt.Println(conjoin(&quot;or&quot;, []string{}))
  95. fmt.Println(conjoin(&quot;or&quot;, []string{&quot;Bob&quot;}))
  96. fmt.Println(conjoin(&quot;or&quot;, []string{&quot;Bob&quot;, &quot;Mike&quot;}))
  97. fmt.Println(conjoin(&quot;or&quot;, []string{&quot;Bob&quot;, &quot;Mike&quot;, &quot;Harold&quot;}))
  98. people := []string{&quot;Bob&quot;, &quot;Mike&quot;, &quot;Harold&quot;, &quot;Academy Award nominee William H. Macy&quot;}
  99. data := map[string]interface{}{&quot;people&quot;: people}
  100. tmpl, err := New(&quot;myyy template&quot;).Parse(&quot;{{ orlist .people }} / {{ andlist .people }}&quot;)
  101. if err != nil {
  102. fmt.Println(&quot;sadness:&quot;, err.Error())
  103. return
  104. }
  105. err = tmpl.Execute(os.Stdout, data)
  106. if err != nil {
  107. fmt.Println(&quot;sadness:&quot;, err.Error())
  108. return
  109. }
  110. }
  111. [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.
  112. </details>
  113. # 答案2
  114. **得分**: 1
  115. 对于从列表中创建正确的英文格式句子的问题可以使用一个函数
  116. 你的复数示例是
  117. <pre>
  118. 这个团队的成员是BobJaneMike
  119. </pre>
  120. 当列表中只有一个元素时你的单数示例是什么例如
  121. <pre>
  122. 这个团队唯一的成员是Bob
  123. </pre>
  124. 当列表中没有元素时你的空示例是什么例如
  125. <pre>
  126. 这个团队没有成员
  127. </pre>
  128. 从邮件合并中创建正确的英文句子和段落是困难的
  129. <details>
  130. <summary>英文:</summary>
  131. For the &quot;creation of a proper English formatted sentence&quot; from a list use a function.
  132. Your plural example is
  133. &lt;pre&gt;
  134. The members of this team are Bob, Jane, and Mike.
  135. &lt;/pre&gt;
  136. What is your singular example where there is only one element in the list? For example,
  137. &lt;pre&gt;
  138. The only member of this team is Bob.
  139. &lt;/pre&gt;
  140. What is your empty example when there are no elements in the list? For example,
  141. &lt;pre&gt;
  142. There are no members of this team.
  143. &lt;/pre&gt;
  144. Creating proper English sentences and paragraphs from a mail merge is hard.
  145. </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:

确定