如何在 Liquid 中对转换为数组的哈希进行排序

发布于 2024-11-15 20:19:32 字数 287 浏览 9 评论 0 原文

我的理解是 Liquid 将 Ruby 哈希转换为数组以在标签中使用。例如,当使用 Jekyll:

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

... 将 site.categories 转换为元组数组,其中 [0] 指的是键,[1] 指的是值列表。

如果我希望上面的类别映射按键(每个元组的 [0])按字母顺序排序,我该怎么做?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

暮年慕年 2024-11-22 20:19:32

这是一个老问题,但我只是花了最后一点时间来为自己解决这个问题。我使用以下代码来实现您(和我)想要的。

{% 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 %}

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 %}
才能让你更想念 2024-11-22 20:19:32

您还可以使用数组代替哈希!

而不是使用这个 yaml:

categories:
  a_category: category description
  another_category: another category description

你可以使用这个:

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

然后你可以像这样迭代,并且顺序将被保留:)

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

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 %}
最单纯的乌龟 2024-11-22 20:19:32

按字母顺序排序的标签的帖子索引(标签名称中不允许有空格):

{% 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 %}

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 %}
花伊自在美 2024-11-22 20:19:32

您可以使用以下方法按键排序(与 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 %}

希望这会有所帮助。

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.

北凤男飞 2024-11-22 20:19:32

您可以为自己省去一些麻烦,扩展 Liquid

例如

# 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)

用法:

{{ myhash | keys | to_ul }}

示例:

# 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>"

如果您觉得幸运,您可以在 github 上查找 for.rb 文件并扩展 for 语法可以更好地处理哈希值:)。

You could save yourself some trouble and extend Liquid:

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 :).

梦冥 2024-11-22 20:19:32

默认的 Liquid 实现和 Jekyll 所做的添加都无法满足您的需求。

恐怕当前的设置根本无法实现您想要的。您必须对 Jekyll 或 Liquid 进行 Monkeypatch 才能使散列按排序顺序返回它们的键。

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.

零崎曲识 2024-11-22 20:19:32

我也想参加这个令人困惑的竞赛(伙计们,number_of_words,认真的吗?)。

此代码逐个标记构建列表标记,在每一步中按字典顺序查找列表中的下一个标记。它的时间复杂度为 O(n²),其中 n 是标签数量。

<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>

顺便说一句,Liquid 的评论看起来沉重得荒谬。

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.

草莓酥 2024-11-22 20:19:32

以下是我解决 Nikos 问题的方法:

{% 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 %}

现在如何让它与 HAML 一起工作......

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文