Answers.Body: <p>Assuming you can't change your data model easily to use relationships pointing to a 2-level Structure for State &gt; Suburb (which would be a more robust approach), you can use the <code>group</code> filter to create 2-dimensional arrays like this:</p>
  <pre class="lang-twig prettyprint-override"><code>{% set buildings = craft.entries.section('buildings').authorId(currentUser.id).all() %}
  {% set buildingsByState = buildings|group(building =&gt; building.state) %}
  &lt;ul&gt;
      {% for state, buildingsInState in buildingsByState %}
          &lt;li&gt;
              &lt;h3&gt;{{ state }}&lt;/h3&gt;
              {% for suburb, buildingsInSuburb in buildingsInState|group(building =&gt; building.suburb) %}
                  &lt;h4&gt;{{ suburb }}&lt;/h4&gt;
                  &lt;ul&gt;
                      {% for building in buildingsInSuburb %}
                          &lt;li&gt;{{ building.title }}&lt;/li&gt;
                      {% endfor %}
                  &lt;/ul&gt;
              {% endfor %}
          &lt;/li&gt;
      {% endfor %}
  &lt;/ul&gt;
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-08-21T11:26:27.337Z
Answers.LastActivityDate: 2023-08-21T11:26:27.337Z
Answers.UserDisplayName: James Smith
Answers.Body: <p>Wasn't that hard actually, just needed to stop and think about it for a bit.</p>
  <pre><code>{% set buildings = craft.entries.authorId(currentUser.id) %}
  {% set states = [] %}
  {% set suburbs = [] %}
  {% for building in buildings %}
      {% set states = states|merge([building.state])|unique %}
      {% set suburbs = suburbs|merge([building.suburb])|unique %}
  {% endfor %}
  
  &lt;ul&gt;
      {% for state in states %}
      &lt;li&gt;
          &lt;div&gt;{{ state }}&lt;/div&gt;
          &lt;ul&gt;
              {% for suburb in suburbs %}
              &lt;li&gt;
                 {{ suburb }}
                  &lt;ul&gt;
                      {% set addresses = craft.entries.authorId(currentUser.id).suburb(suburb) %}
                      {% for address in addresses %}
                      &lt;li&gt;{{ address.title }}&lt;/li&gt;
                      {% endfor %}
                  &lt;/ul&gt;
              &lt;/li&gt;
              {% endfor %}
          &lt;/ul&gt;
      &lt;/li&gt;
      {% endfor %}
  &lt;/ul&gt;
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-08-18T08:43:32.913Z
Answers.Text: Be careful with this solution - you've created an N+1 problem here by having a query inside a loop - and a nested loop at that, which will compound the problem. Every entry that gets added will progressively degrade the performance of this. Turn on your template debugger and keep an eye on the DB query count and timing. Are your states and suburbs relationship fields (entries/categories) or plain text/dropdowns?
Answers.UserDisplayName: James Smith
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-08-21T00:09:42.160Z
Answers.Text: @JamesSmith Plain text fields
Answers.UserDisplayName: Tyssen
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-08-21T10:53:25.323Z
Answers.Text: You also seem to be looping through _all_ suburbs here, not just the ones that belong to the current state. If it's not too late I'd recommend you refine your content model so that states and suburbs are a 2-level Structure (a suburb can never be a child of more than one state, so this is a suitable setup). It'll also improve your data quality by avoiding typos or alternate spellings. Even someone putting a space or capital letter in the wrong place could spoil your output.
Answers.UserDisplayName: James Smith
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-08-18T01:27:19.667Z
Answers.LastActivityDate: 2023-08-18T01:27:19.667Z
Answers.UserDisplayName: Tyssen
Body: <p>I have a section for addresses which has fields for <code>address</code>, <code>state</code>, <code>suburb</code> and <code>postcode</code>. On the front end, I want to display them like this:</p>
  <pre><code>State 1
  - Suburb 1
  -- Address 1
  -- Address 2
  - Suburb 2
  -- Address 1
  -- Address 2
  </code></pre>
  <p>so in other words, they'd be grouped by their state and then by their suburb. How would I go about doing that?</p>
  
Tags: <group>
Title: Group entries by custom fields
ThreadText: # Group entries by custom fields
  
  (Asked by: username_0 on 2023-08-18)
  
  I have a section for addresses which has fields for `address`, `state`, `suburb` and `postcode`. On the front end, I want to display them like this:
  
  ```
  State 1
  - Suburb 1
  -- Address 1
  -- Address 2
  - Suburb 2
  -- Address 1
  -- Address 2
  
  ```
  
  so in other words, they'd be grouped by their state and then by their suburb. How would I go about doing that?
  
  **Tags:** group
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2023-08-21. Score: 2 | Accepted answer
  
  Assuming you can't change your data model easily to use relationships pointing to a 2-level Structure for State > Suburb (which would be a more robust approach), you can use the `group` filter to create 2-dimensional arrays like this:
  
  ```twig
  {% set buildings = craft.entries.section('buildings').authorId(currentUser.id).all() %}
  {% set buildingsByState = buildings|group(building => building.state) %}
  <ul>
      {% for state, buildingsInState in buildingsByState %}
          <li>
              <h3>{{ state }}</h3>
              {% for suburb, buildingsInSuburb in buildingsInState|group(building => building.suburb) %}
                  <h4>{{ suburb }}</h4>
                  <ul>
                      {% for building in buildingsInSuburb %}
                          <li>{{ building.title }}</li>
                      {% endfor %}
                  </ul>
              {% endfor %}
          </li>
      {% endfor %}
  </ul>
  
  ```
  
  
  ---
  
  ### Answer by username_0 on 2023-08-18. Score: 1
  
  Wasn't that hard actually, just needed to stop and think about it for a bit.
  
  ```
  {% set buildings = craft.entries.authorId(currentUser.id) %}
  {% set states = [] %}
  {% set suburbs = [] %}
  {% for building in buildings %}
      {% set states = states|merge([building.state])|unique %}
      {% set suburbs = suburbs|merge([building.suburb])|unique %}
  {% endfor %}
  
  <ul>
      {% for state in states %}
      <li>
          <div>{{ state }}</div>
          <ul>
              {% for suburb in suburbs %}
              <li>
                 {{ suburb }}
                  <ul>
                      {% set addresses = craft.entries.authorId(currentUser.id).suburb(suburb) %}
                      {% for address in addresses %}
                      <li>{{ address.title }}</li>
                      {% endfor %}
                  </ul>
              </li>
              {% endfor %}
          </ul>
      </li>
      {% endfor %}
  </ul>
  
  ```
  
  > **Comments:**
  > **username_1**: Be careful with this solution - you've created an N+1 problem here by having a query inside a loop - and a nested loop at that, which will compound the problem. Every entry that gets added will progressively degrade the performance of this. Turn on your template debugger and keep an eye on the DB query count and timing. Are your states and suburbs relationship fields (entries/categories) or plain text/dropdowns?  
  > **username_0**: @username_1 Plain text fields  
  > **username_1**: You also seem to be looping through _all_ suburbs here, not just the ones that belong to the current state. If it's not too late I'd recommend you refine your content model so that states and suburbs are a 2-level Structure (a suburb can never be a child of more than one state, so this is a suitable setup). It'll also improve your data quality by avoiding typos or alternate spellings. Even someone putting a space or capital letter in the wrong place could spoil your output.  
  
  ---
  
  