Merging maps but it's ordering them alphabetically

Considering something simple like

{{ merge (dict "a" "a") (dict "z" "z") (dict "b" "b") }}

How do I keep the original order?

Go: maps are unordered

https://go.dev/ref/spec#Map_types

A map is an unordered group of elements…

https://go.dev/blog/maps#iteration-order

When iterating over a map with a range loop, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next. If you require a stable iteration order you must maintain a separate data structure that specifies that order.

Go templates: maps are sorted by key when iterating with a range loop

https://pkg.go.dev/text/template#hdr-Actions

{{range pipeline}} T1 {{end}}

The value of the pipeline must be an array, slice, map, or channel. If the value of the pipeline has length zero, nothing is output; otherwise, dot is set to the successive elements of the array, slice, or map and T1 is executed. If the value is a map and the keys are of basic type with a defined order, the elements will be visited in sorted key order.

Hugo

With Hugo, it appears that maps are sorted by key whenever they are accessed—the behavior is not limited to range loops. I’m not sure why that is. For example:

{{ printf "%#v" $m }} --> output will be sorted by key

Ordered data

Arrays/slices are ordered. So you could do something like:

{{ $m := slice (dict "a" "foo") (dict "z" "bar") (dict "b" "baz") }}

Visualizing the data structure:

[
  {
    "a": "foo"
  },
  {
    "z": "bar"
  },
  {
    "b": "baz"
  }
]

To render the key/value pairs:

{{ range $m }}
  {{ range $k, $v := . }}
    {{ $k }}: {{ $v }}<br>
  {{ end }}
{{ end }}
1 Like

Thanks, using a slice and nested ranges did the trick.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.