4
votes

When iterating through an array of files in the _data folder, what is the default criteria for sorting the files?

At first I was expecting it to be sorted alphabetically, but after some testing I realized it was not. Still, I couldn't figure out what was the criteria being used to sort the files.

{%- for file in site.data.folder -%}
{{ file | inspect }}
<br />
<br />
{%- endfor -%}

From what I understood file is an array containing the filename as the first element and the data as the second element, so I'm not sure using sort with any property name would work. When I tried I had the error message:

Liquid Exception: no implicit conversion of String into Integer

When using sort with no arguments, I could return the files sorted by filename alphabetic order:

{%- assign files = site.data.folder | sort -%}
{%- for file in files -%}
{{ file | inspect }}
<br />
<br />
{%- endfor -%}

So my questions are:

  • What is the default sorting criteria for _data files?
  • Is sorting in relation to an object property possible? (I'm thinking the issue with that one is having an array and not the pure objects when you access site.data.folder)

Example:

After creating the default Jekyll page, I created the _data/folder directory, where I'd include 5 random .json files:

_data/folder/a.json
_data/folder/b.json
_data/folder/c.json
_data/folder/d.json
_data/folder/e.json

Each of them have the following content:

_data/folder/a.json:

{"name":"Mike"}

_data/folder/b.json:

{"id":"4343"}

_data/folder/c.json:

[{"age":"29"},{"job":"journalist"}]

_data/folder/d.json:

{"name":"John"}

_data/folder/e.json

{"haircolor":"green"}

With those files in place, I created a page named page.html on the root directory with:

---
---
<pre>{{ site.data.folder | inspect }}</pre>

<br />
<br />

{%- for file in site.data.folder -%}
<pre>{{ file | inspect }}</pre>
<br />
{%- endfor -%}

And the output of that page was:

{"e"=>{"haircolor"=>"green"}, "c"=>[{"age"=>"29"}, {"job"=>"journalist"}], "d"=>{"name"=>"John"}, "a"=>{"name"=>"Mike"}, "b"=>{"id"=>"4343"}}



["e", {"haircolor"=>"green"}]


["c", [{"age"=>"29"}, {"job"=>"journalist"}]]


["d", {"name"=>"John"}]


["a", {"name"=>"Mike"}]


["b", {"id"=>"4343"}]

The files were not ordered alphabetically, but instead in some apparently random order. I can get them in alphabetical order by using:

---
---
<pre>{{ site.data.folder | sort | inspect }}</pre>

<br />
<br />

{%- assign folder = site.data.folder | sort -%}
{%- for file in folder -%}
<pre>{{ file | inspect }}</pre>
<br />
{%- endfor -%}

Output:

[["a", {"name"=>"Mike"}], ["b", {"id"=>"4343"}], ["c", [{"age"=>"29"}, {"job"=>"journalist"}]], ["d", {"name"=>"John"}], ["e", {"haircolor"=>"green"}]]



["a", {"name"=>"Mike"}]


["b", {"id"=>"4343"}]


["c", [{"age"=>"29"}, {"job"=>"journalist"}]]


["d", {"name"=>"John"}]


["e", {"haircolor"=>"green"}]

But it's still unclear what is the ordering criteria on the call without sort.

1
To check what data you're actually dealing with, try "inspecting" with: <pre>{{ site.data }}</pre>ashmaroli
From what I can see here, it is an object with hashes pointing to their value. The hashes are the filenames and the values are the objects containing the data from the file. I still don't get why they are ordered that way by default. It would make sense to me if they were loaded alphabetically, but so far it looks a little random (though it doesn't change the order if you load the same files again).IanC
I'm using Jekyll on Windows.. and at my end, the hash has its keys ordered alphabetically (same output over multiple build sessions), irrespective of when the files are modified.. (so that's out the window as well..)ashmaroli
@ashmaroli I just tested again here with a completely clear Jekyll site, and again the sorting is out of order (non-alphabetical). But I'm running on Linux, maybe the Windows version behaves differently? I'll edit the question to include the files on the data folder and their content, just as an example.IanC
There's no separate version for Windows.. I'm using the same Rubygem as you are.. the difference is at much lower-level within the Ruby Interpreters for various platforms.. Since you have a solution at hand, I'd suggest to go with it.. IMO, this is not a Jekyll issue.. but if you feel otherwise, I suggest you open an issue at the Jekyll GitHub Repoashmaroli

1 Answers

1
votes

Going from @ashmaroli's assumption that this was not a Jekyll's issue, I started making a little bit of research about file ordering and ran into the following resources:


File ordering behavior while using Dir on Ruby

Indeterministic File order using Dir

The link describes a counter intuitive behavior when loading multiple dependencies. If the order the files are loaded matter the shortcut below could result in they being loaded in a different order than the expected.

Dir[File.join(File.dirname(__FILE__), 'example/*.rb')].each{ |f| require f }

This is apparently due to the underlying glob system call according to the answer in the link.


Python glob ordering

How is Pythons glob.glob ordered?

In the SO question above, the user is asking why the returned glob file order in Python is different than the order on the output of ls -l. Even though the question is about Python and not Ruby, the underlying call to the OS is likely the same. The OS is not required to deliver the files in any order, so they should be sorted after the call.

The first answer states that if you run ls -U you get the unordered list of files, which matches the order I have here when I make a list of _data objects on Jekyll without sorting. So this is most likely the cause of the weird ordering: it's OS dependent.

Since Jekyll orders the _post files, I think it wouldn't be a major issue to order _data files by default as well, to avoid any confusion. But as it was stated before in the question itself, it can be easily done with the sort filter.