Filtering an array in a Liquid/Jekyll template
Asked Answered
W

3

7

Most Liquid "filters" are actually "map"s in the functional programming sense: you take an array, you apply a function to each element and return the transformed array. I'd like instead to "filter": I want to return only those items in the array that match a certain condition. How can I do that?

Specifically, I'm trying to improve this template:

Authors: 
{% for c in site.data["contributors"] %}
  {% assign contributor = c[1] %}{% if contributor.role contains "author" %}{{contributor.name.given}} {{contributor.name.family}}{% endif %}{% endfor %}

which, prettified, looks like this:

Authors: 
{% for c in site.data["contributors"] %}
  {% assign contributor = c[1] %}
  {% if contributor.role contains "author" %}
    {{contributor.name.given}} {{contributor.name.family}}
  {% endif %}
{% endfor %}

where its data looks like this:

ianbarber:
  name:
    given: Ian
    family: Barber
  org:
    name: Google
    unit: Developer Relations
  country: UK
  role:
    - engineer
  homepage: http://riskcompletefailure.com
  google: +ianbarber
  twitter: ianbarber
  email: [email protected]
  description: "Ian is a DRE"

samdutton:
  name:
    given: Sam
    family: Dutton
  org:
    name: Google
    unit: Developer Relations
  country: UK
  role:
    - author
  google: +SamDutton
  email: [email protected]
  description: "Sam is a Developer Advocate"

(example taken from here).

The problem with this approach is that a newline is output if the current element doesn't match the condition, as you can see in https://developers.google.com/web/humans.txt.

How can I fix this?

Wavy answered 27/8, 2014 at 8:31 Comment(1)
'Most Liquid "filters" are actually "map"' +!. Ironic and annoying the only thing not part of Liquid's "filters" is an actual f#%$ing filter!Shum
I
4

If you want to get rid of the newline if the condition doesn't match, try to remove the unwanted newlines in the if and for clauses:

{% for c in site.data["contributors"] %}{% assign contributor = c[1] %}{% if contributor.role contains "author" %}
  {{contributor.name.given}} {{contributor.name.family}}{% endif %}{% endfor %}

That may not look nice in the source, but it will probably get rid of the newline in the output.

Note: I didn't try this, but similar rearranging helped me get rid of unwanted newlines. You may even have to put the {% if ... on the extreme left, so the indentation does not get included.

Interstadial answered 27/8, 2014 at 18:45 Comment(3)
Nope, this doesn't work. In fact, this is what they do in the codebase, while I prettified a little in my question. I guess I should say add this caveat.Wavy
I changed the formatting. Try it again. The problem is that there are newlines in the for and if clauses which get inserted where you don't want them. They should only get inserted where you want them. So reformatting the code should get rid of these newlines. In my code, I had to experiment with this too, to avoid newlines.Interstadial
Every newline and space is inserted, even if you think it is just for prettyfying and formatting. I often replace newlines with a newline+number to see which gets placed where. Then I remove the newlines I don't want (and the numbers) in the final sources.Interstadial
S
11

Jekyll 2.0 has a where filter. See docs. Example - from doc:

{{ site.members | where:"graduation_year","2014" }}
{{ site.members | where_exp:"item", "item.graduation_year == 2014" }}
Shum answered 4/11, 2017 at 11:35 Comment(0)
I
4

If you want to get rid of the newline if the condition doesn't match, try to remove the unwanted newlines in the if and for clauses:

{% for c in site.data["contributors"] %}{% assign contributor = c[1] %}{% if contributor.role contains "author" %}
  {{contributor.name.given}} {{contributor.name.family}}{% endif %}{% endfor %}

That may not look nice in the source, but it will probably get rid of the newline in the output.

Note: I didn't try this, but similar rearranging helped me get rid of unwanted newlines. You may even have to put the {% if ... on the extreme left, so the indentation does not get included.

Interstadial answered 27/8, 2014 at 18:45 Comment(3)
Nope, this doesn't work. In fact, this is what they do in the codebase, while I prettified a little in my question. I guess I should say add this caveat.Wavy
I changed the formatting. Try it again. The problem is that there are newlines in the for and if clauses which get inserted where you don't want them. They should only get inserted where you want them. So reformatting the code should get rid of these newlines. In my code, I had to experiment with this too, to avoid newlines.Interstadial
Every newline and space is inserted, even if you think it is just for prettyfying and formatting. I often replace newlines with a newline+number to see which gets placed where. Then I remove the newlines I don't want (and the numbers) in the final sources.Interstadial
P
0

@Rudy Velthuis answer But indented.. (Could not edit answer as the queue is full)

{% for c in site.data["contributors"] %}
    {% assign contributor = c[1] %}
    {% if contributor.role contains "author" %}
        {{contributor.name.given}} 
        {{contributor.name.family}}
    {% endif %}
{% endfor %}

Why liquid community so agains indentation I do not know..

Porous answered 24/7, 2021 at 11:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.