How to select keys from a Dict?

My WebSite uses a Json data file. To select a random element of this dataset, i want to select all keys of this dictionary.
I scanned the documentation but found no hint on how to perform this operation (probably with apply).

Sample Data “cover.json”:

{
	"uhd": {
		"img": "uhd_img_1312pv1c1-cc.jpg",
		"credits": "ESO/B. Tafreshi",
		"url": "twanight.org",
		"caption": ""		
	},
	"alma": {
		"img": "alma-jfs-2010-10.jpg",
		"credits": "ESO/B. Tafreshi",
		"url": "twanight.org",
		"caption": ""
	}
}

Accessing the records by their keywords is no problem…

{{ $title := .Title }}
{{ $baseUrl := .Site.BaseURL }}
{{ with .Site.Data.cover.uhd }}
<section id="cover-report" style="background: #222 url('{{ $baseUrl }}/img/fullscreen/{{ .img }}') no-repeat center top;">
	<div id="cover-caption">
		<div class="container">
	        <div class="col-sm-10 offset-sm-1">
                <h1>{{ $title }}</h1>
                {{ if  .caption }}
                <p>{{ .caption }}</p>
                {{ end }}
	        </div>
		</div>
		{{ if .credits }}
		<div class="credits">{{ .credits }}{{ if .url }} (<a class="external" href="http://{{ .url }}">{{ .url }}</a>){{ end }}</div>
		{{ end }}
	</div>
</section>
{{ end }}

(This partial is still incomplete.)

I’d like to select a random cover-image in case the page did not ask for a specific background. Therefore I’d expected to select it something like this:

{{ $randomCoverKey := SOME_KEY_EXTRACTING_FUNCTION .Site.data.cover | shuffle | first 1 }}
{{ with index .Site.date.cover $randomCoverKey }}

Can you share your code, or at least your JSON data file?

Hi,

Do you want to select one element at random? Or all the keys?

You can use range to go through all the keys/values.

As for the random element, you could put the keys into a list and select one at a random index, then use that to select the corresponding element. So something like:

{{ $keys := slice }}<!-- hold all the keys in an array -->
{{ $cov := .Site.Data.cover }}<!-- for brevity -->

{{ range $key, $val := $cov }}
  <!-- append each key to list of keys -->
  {{ $keys = $keys | append $key }}
{{ end }}

<!-- use seq to generate a series from 0 to len-1, then shuffle, then get the first number -->
{{ $rand := index (shuffle (seq 0 (sub (len $keys) 1)) ) 0 }}

<!-- $cov[$keys[$rand]] -->
{{ $randomelement := index $cov (index $keys $rand) }}

2 Likes

Thank you, that solved my problem.

Finally i’ve got what i wanted using the code below.

{{ $keys := slice }}
{{ $cov := .Site.Data.cover }}
{{ range $key, $val := $cov }}{{ $keys = $keys | append $key }}{{ end }}
{{ $cover := .Params.pageCover | default (index $cov (index $keys (index (shuffle (seq 0 (sub (len $keys) 1)) ) 0))) }}
{{ with $cover }}
<section id="cover-page" style="background: #222 url('{{ $baseUrl }}/img/fullscreen/{{ .img }}') no-repeat top center;">
{{ end }}

The actual code is slightly more complicated because the post might decide to define the cover image that should be visible on the top of the page. But for all pages that are indecisive this made my day.

While still under massive change you might have look at my first Hugo-made website:

http://www.reswi.de/avd/

There is still work to be done but i’m slowly getting there.