How to group data by first letter and order it alp

2019-01-29 00:18发布

问题:

I have managed to order all the data alphabetically but what I can't do is group it by first letter and also display the first letter like below:

A

  • apple
  • arrow

B

  • band
  • blur

and so on...

Here is my code for displaying the ordered data.

---
layout: default
---
{% capture thelistings %}
  {% for listing in site.data.terminology %}
    <li>{{ listing.term }}: {{ listing.definition }}</li>
  {% endfor %}
{% endcapture %}
{% assign allsortedlistings = thelistings | split:"   " | sort %}

    <ul>
{% for allterms in allsortedlistings %}
        {{ allterms }}
{% endfor %}
    </ul>

This outputs:

  • again: now it is here
  • aunt: another explanation for two
  • borrow: something from someone
  • brother: new explanation for one
  • father: this is it
  • forbidden: fruit
  • uncle: and last one for three, with the use of comma fin
  • utah: this is a state

回答1:

Well, you need to check somewhere whether the first letter of the current term differs from the first letter of the previous term.

Try this:

{% assign lastletter = "" %}

{% for listing in site.data.terminology %}

    {% assign tmpletter = listing.term | slice: 0 | upcase %}

    {% if tmpletter != lastletter %}
        <h1>{{ tmpletter }}</h1>
    {% endif %}

    {{ listing.term }}: {{ listing.definition }}<br>

    {% assign lastletter = tmpletter %}

{% endfor %}

I just save the first letter of the current term to the variable tmpletter.
(slice truncates the string and upcase converts it to uppercase because I want to display it in uppercase)

Then, if it's different from the first letter of the last term, I display it.

HTML output:

<h1>A</h1>
again: now it is here<br>
aunt: another explanation for two<br>
<h1>B</h1>
borrow: something from someone<br>
brother: new explanation for one<br>
<h1>F</h1>
father: this is it<br>
forbidden: fruit<br>
<h1>U</h1>
uncle: and last one for three, with the use of comma fin<br>
utah: this is a state<br>

(I didn't bother with getting the <ul><li> stuff right, you'll probably get this to work by yourself)


the code works well but only if the csv file is already ordered alphabetically, I need the code to do both the ordering and the adding of the first letter.

Okay, then you need to combine your code and my code, i.e. you need to apply my "determine whether the first letter changed" part to your {% for allterms in allsortedlistings %} part.

Something like this:

{% capture thelistings %}
  {% for listing in site.data.terminology %}
    {{ listing.term }}: {{ listing.definition }}
  {% endfor %}
{% endcapture %}
{% assign allsortedlistings = thelistings | split:"   " | sort %}

{% assign lastletter = "" %}

    <ul>
{% for allterms in allsortedlistings %}

    {% assign tmpletter = allterms | strip | slice: 0 | upcase %}

    {% if tmpletter != lastletter %}
        <li>{{ tmpletter }}</li>
    {% endif %}

        <li>{{ allterms }}</li>

    {% assign lastletter = tmpletter %}

{% endfor %}
    </ul>

This is not the 100% finished solution, you still need to figure out how to end/start the <ul> sections when the first letter changes.

Plus, there's an empty <li> at the beginning, probably because you're splitting by empty strings and thelistings contains a lot of empty strings (because of the line breaks and indentations inside {% capture thelistings %}...{% endcapture %}.

(for the same reason, I needed to strip all blanks from the string in the {% assign tmpletter = ... line, to find the first character that isn't a blank)