How to sort a hash converted to an array in Liquid

本小妞迷上赌 提交于 2019-11-30 23:13:11

问题


My understanding is that Liquid converts Ruby Hashes to arrays for use in tags. For example, when using Jekyll:

{% for category in site.categories %}
    <li>{{ category[0] }}</li>
{% endfor %}

... converts site.categories to an array of tuples in which [0] refers to the key, [1] the list of values.

If I wanted the above category map to be sorted alphabetically by the key ([0] of each tuple) how can I do this?


回答1:


Neither the default Liquid implementation nor the additions made by Jekyll allow for what you want.

I'm afraid what you want is simply not possible with the current setup. You would have to monkeypatch Jekyll or Liquid in order to make the hashes return their keys in a sorted order.




回答2:


This is an old question, but I just spend the last little while figuring this out for myself. I used the following code to achieve what you ( and I ) wanted.

{% capture get_items %}
 {% for cat in site.categories %}
   {{ cat | first }}
 {% endfor %}
{% endcapture %}
{% capture num_words %}
 {{ get_items | split:' ' |  sort | join:' ' | number_of_words }}
{% endcapture %}
{% for item in (1..num_words) %}
 <li>{{ get_items | split:' ' |  sort | join:' ' | truncatewords:item | remove:'.    ..' |    split:' ' | last }}</li>
{% endfor %}



回答3:


You can also use arrays instead of hashes!

Instead of using this yaml:

categories:
  a_category: category description
  another_category: another category description

You can use this one:

categories:
  - {name: 'a category', description: 'category description'}
  - {name: 'another category', description: 'another category description'}

And then you can iterate like this, and order will be preserved :)

{% for category in site.categories %}
  <li>{{ category['name'] }}</li>
{% endfor %}



回答4:


Index of posts by alphabetically sorted tags (spaces not allowed in tag names):

{% capture tags %}
  {% for tag in site.tags %}
    {{ tag[0] }}
  {% endfor %}
{% endcapture %}
{% assign sortedtags = tags | split:' ' | sort %}

{% for tag in sortedtags %}
  <h4>#{{ tag }}</h4>
  <ul>
  {% for post in site.tags[tag] %}
    <li>
      <span>{{ post.date | date_to_string }}</span>
      <a href="{{ post.url }}">{{ post.title }}</a>
    </li>
  {% endfor %}
  </ul>
{% endfor %}



回答5:


You can sort by the key using the following method (that is compatible with Github Pages):

{% assign sorted_categories = (site.categories | sort:0) %}
{% for category in sorted_categories %}
   <!-- Using the 'capitalize' filter in Liquid Tags - you can leave this out -->
   <li>{{category[0] | capitalize }}</li>

   {% assign sorted_catposts = (category[1] | sort: 'title', 'last') %}
   {% for catpost in sorted_catposts %}
     <!-- The posts within each category are now alphabetically sorted by title -->
     <!-- Do stuff with each post in each category -->
   {% endfor %}
{% endfor %}

Hope this helps.




回答6:


I also want to be part of this obfuscated competition (dudes, number_of_words, seriously?).

This code is building the list tag by tag, looking for the next tag in lexicographic order in the list at each step. It's in O(n²) where n is the number of tags.

<section>
  <h1>Pick a tag!</h1>
  <ul id="recent_posts">
    {% assign current_tag = ' ' %}
    {% for t in site.categories %}
      <li class="post">
        {% assign next_tag = 'ZZZ' %}
        {% for item in site.categories %}
          {% assign tag = item.first %}
          {% if tag > current_tag and tag < next_tag %}
            {% assign next_tag = tag %}
          {% endif %}
        {% endfor %}
        {{ next_tag | category_link }} {{ site.categories[next_tag].size }}
        {% assign current_tag = next_tag %}
      </li>
    {% endfor %}
  </ul>
</section>

BTW, Liquid comments look absurdly heavy.




回答7:


You could save yourself some trouble and extend Liquid:

  • You can create your own tag blocks, and
  • You can create your own filters

e.g.

# https://gist.github.com/dnozay/026862f5d65dcb8b4353

module Jekyll
  module Toolbox
    def keys(hash)
      hash.keys
    end
    def to_ul(collection)
      result = ''
      collection.each do |item|
        result << "<li>#{item}</li>"
      end
      result
    end
  end
end

Liquid::Template.register_filter(Jekyll::Toolbox)

Usage:

{{ myhash | keys | to_ul }}

Examples:

# https://gist.github.com/dnozay/026862f5d65dcb8b4353

@context = { 'myhash' => { 'b' => 'B', 'a' => 'A', 'c' => 'C' } }
@template = Liquid::Template.parse("{{ myhash | keys | to_ul }}")
@template.render(@context)  # => "<li>b</li><li>a</li><li>c</li>"
@template = Liquid::Template.parse("{{ myhash | keys | sort | to_ul }}")
@template.render(@context)  # => "<li>a</li><li>b</li><li>c</li>"

If you feel lucky you can look on github for the for.rb file and extend the for syntax to handle hashes better :).




回答8:


Here's how I fixed Nikos problem:

{% capture get_items %}
   {% for cat in site.categories %}
    {{ cat | first | replace: ' ', '_' }}
   {% endfor %}
{% endcapture %}
{% capture num_words %}
  {{ get_items | split:' ' |  sort | join:' ' | number_of_words }}
{% endcapture %}
{% for item in (1..num_words) %}
  <li>{{ get_items | split:' ' |  sort | join:' ' | truncatewords:item | remove:'...' | split:' '  | last | replace: '_', ' ' }}</li>
{% endfor %}

Now how to get this working with HAML...



来源:https://stackoverflow.com/questions/6387540/how-to-sort-a-hash-converted-to-an-array-in-liquid

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!