Sorting by generated value

I finally worked out a way to get Jekyll/Liquid to sort by a generated value — e.g. the number of MPs each party has. (For context, see the previous Count of Party Members post).

But boy is it ugly!

When we’re looping around the parties, as well as initialising an MP counter to 0, we also initialise a prefix to ‘a’:


{% for party in site.data.parties %}
  {% assign mps = 0 %}
  {% assign prefix = 'a' %}

Then, when we find a suitable match, as well as incrementing the counter, we also extend the prefix by another ‘a’:


        {% assign prefix = prefix | append:'a' %}
        {% assign mps = mps | plus:1 %}

But instead of simply outputting this each time through the loop, we put the whole block in a {% capture party_with_count %}, to which we feed a string of {{ prefix }}+++{{party.name | replace: ' ', '---'}}+++{{ party.id }}+++{{ mps }}.

This is carefully constructed not to have any spaces, so we can then split the full output (of one of these strings per party) on spaces, which we can then sort (on the prefix, which will be ‘a’ for parties with one member, ‘aaaaa’ for parties with five members, ‘aaaaaaaaaaaaaaaaaaaaaaaaaaaa’ for parties with twenty-eight members, etc), split back into the constituent parts, and display!


{% assign sortedparties = party_with_count | split:' ' | sort %}
<ul>
  {% for party in sortedparties reversed %}
    {% assign parts = party | split:'+++' %}
    <li><a href="/party/{{ parts[2] | split:"/" | last }}.html">{{ parts[1] | replace: '---', ' ' }}</a> ({{ parts[3] }})</li>
  {% endfor %}
</ul>

This basically works around two different things I couldn’t work out how to do:

  1. Create a nested data structure. The only way I could even find to create a list was to create a string that I could ‘split’.
  2. Sort numerically. If I could just put the count at the start of the string and sort by that, I wouldn’t need this ever-growing prefix, but sort only seems to sort alphabetically (thus placing 12 between 1 and 2)

For now I’m happy that it works (see code, and output), but I’d be very happy if someone could show me a better way to do this!

Leave a Reply

Your email address will not be published. Required fields are marked *