How to create a first-letter indexed list

Think about the address book on your mobile phone scroll it down and you see that all the titles above are first-letters from the following entries. In this article you will find a solution how to achieve this with Hugo.

Assumptions

Given you have just a list of names and want to have them ordered and grouped by first letters like:

Assumed list:

$names := slice "Abby" "Alfred" "Benjamin" "Beth" "Xavier"
# ["Abby", "Alfred", "Benjamin", "Beth", "Xavier"]

Wished output:

A
- Abby
- Alfred

B
- Benjamin
- Beth

X
- Xavier

Process

  1. Iterate through the list using range
  2. Extract the first letter of the name
  3. Compare the current first letter with the first letter of the actual name
  4. Update the current first letter if its different from the one before and close / open a new list entry

Solution

$names := slice "Abby" "Alfred" "Benjamin" "Beth" "Xavier"

{{ $.Scratch.Set "FirstLetter" (index (split (index $names 0) "") 0) }}
<!-- defined the first letter from the first entry of the list !-->

<h2>{{ ($.Scratch.Get "FirstLetter") }}</h2>
<ul>
    {{ range $names }}

        {{ $firstLetter := index (split . "") 0 }}
        <!-- extract the current first letter with the `split` method !-->

        <!-- check if the current $firstLetter is not equal (ne) to the recently stored !-->
        {{ if ne $firstLetter ($.Scratch.Get "FirstLetter") }}
            <!-- if its a new one - close last ul and start with a new headline !-->
            </ul>
            <h2>{{ $firstLetter }}</h2>
            <ul>
            <!-- update current first letter using Scratch !-->
            {{ $.Scratch.Set "FirstLetter" $firstLetter }}
        {{ end }}

        <li>{{ . }}</li>
        <!-- Display the current name within an li tag !-->

    {{ end }}
</ul>