Hi there ,
You might have had the challenge of sorting an array that is associated/linked to another one. Unfortunately, we don’t have a way to create dictionaries in liquid so we can’t tell the language that those arrays have a relationship.
Let’s say you have these 2 arrays:
In our code we would have this:
{% assign values_array = values_array | split:'' %}
{% assign name_array = name_array | split:'' %}
{% push 'A' to:name_array %} {% push 500 to:values_array %}
{% push 'B' to:name_array %} {% push 300 to:values_array %}
{% push 'C' to:name_array %} {% push 100 to:values_array %}
{% push 'D' to:name_array %} {% push 500 to:values_array %}
Imagine you want to sort this table by values (lowest to highest). We can do so by using the sort
filter in the following way:
{% assign sorted_values_array = values_array | sort %}
However if I want to now print both arrays we will see this:
{% comment %}Unsorted table{% endcomment %}
{% for sorted_value in sorted_values_array %}
{{ name_array[forloop.index0] }} {{ sorted_value }}
{% endfor %}
As you can see, the values are sorted but the name_array
remains static (i.e. A is 100 and not 500 as it should).
To solve this, we can create a workaround in liquid using a similar logic than the one used with vlook-ups in excel. First we run through the sorted_values_array
and then we create a nested loop on the unsorted values_array
that will look for the corresponding match:
{% comment %}Sorted table without index{% endcomment %}
{% for sorted_value in sorted_values_array %}
{% for unsorted_value in values_array %}
{% if sorted_value == unsorted_value %}
{% assign name = name_array[forloop.index0] %}
{% break %}
{% endif %}
{% endfor %}
{{ name }} {{ sorted_value }}
{% endfor %}
Now we see that the name_array
match the values, but we still have an issue related to duplicate amounts as we have two amounts equal to 500. What the code does in both cases is finding the first 500 match which is A and prints it.
In order to solve this, we need to tell liquid that it has already printed that name and needs to keep looking. For that, we have to create an index array
that saves the corresponding index value and checks whether it’s been already used:
{% comment %}Sorted table{% endcomment %}
{% assign index_array = index_array | split:'' %}
{% for sorted_value in sorted_values_array %}
{% for unsorted_value in values_array %}
{% assign get_name = true %}
{% assign index = index+1 %}
{% if sorted_value == unsorted_value %}
{% for item in index_array %}
{% if item == index %}
{% assign get_name = false %}
{% break %}
{% endif %}
{% endfor %}
{% if get_name != false %}
{% assign name = name_array[forloop.index0] %}
{% push index to:index_array %}
{% assign index = 0 %}
{% break %}
{% endif %}
{% endif %}
{% endfor %}
{{ name }} {{ sorted_value }}
{% endfor %}
The above is your final code to solve the dictionary limitation in liquid. We keep pushing the index
value in the index_array
, then we check whether this index is already there in order to avoid printing the same name and keep on looking for the next one.
I hope you find this useful!
Best,
Borja