Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

detect last item inside an array using range inside go-templates

This program outputs simply

1,4,2,

but I would like to print

1,4,2.

As you can see the comma is printed after each items of an array.

package main

import "os"
import "text/template"

func main() {
    params := map[string]interface{}{
        "items": [3]int{1, 4, 2},
    }
    tpl := "{{range $i, $el := .items}}{{$el}},{{end}}"
    lister, _ := template.New("foo").Parse(tpl)
    lister.Execute(os.Stdout, params)
}

Is there a way to change {{range $i, $el := .items}}{{$el}},{{end}} and be sure that last item will print "." instead of ","

like image 577
sensorario Avatar asked Apr 29 '18 09:04

sensorario


2 Answers

You can use

tpl := "{{range $i, $el := .items}}{{if $i}},{{end}}{{$el}}{{end}}."

to achieve that. The trick is to emit the comma separator first, but not for the first item in the range.

like image 70
fhe Avatar answered Oct 05 '22 02:10

fhe


In the simple example you posted, easiest is what "fhe" posted: you can easily check if the current index is the first, and output a comma after non-first elements. And finally output a trailing dot.

If in a more complicated example you do need to detect the last item, or it may be that the list you iterate over may be empty (and thus the trailing dot would be a mistake), you may register a custom function to tell if the current index is the last:

lister := template.Must(template.New("foo").Funcs(template.FuncMap{
    "IsLast": func(i, size int) bool { return i == size-1 },
}).Parse(tpl))

And use the following template then:

tpl := "{{range $i, $el := .items}}{{$el}}{{if IsLast $i (len $.items)}}.{{else}},{{end}}{{end}}"

Then the output will be (try it on the Go Playground):

1,4,2.

A variation of this could be to register a custom function which calculates the last index from the length (lastIdx = length - 1), and then inside the {{range}} you can do a simple comparison:

tpl := "{{$lastIdx := LastIdx (len .items)}}{{range $i, $el := .items}}{{$el}}{{if eq $lastIdx $i}}.{{else}},{{end}}{{end}}"
lister := template.Must(template.New("foo").Funcs(template.FuncMap{
    "LastIdx": func(size int) int { return size - 1 },
}).Parse(tpl))

Output will be the same. Try it on the Go Playground.

like image 31
icza Avatar answered Oct 05 '22 02:10

icza