Cómo ordenar un hash convertido a una matriz en líquido
Pregunta
Entiendo que el líquido convierte los hashes de rubí en matrices para su uso en etiquetas. Por ejemplo, cuando se usa Jekyll:
{% for category in site.categories %}
<li>{{ category[0] }}</li>
{% endfor %}
... convierte el sitio. Categorías a una matriz de tuplas en la que [0] se refiere a la clave, [1] la lista de valores.
Si quería que el mapa de categoría anterior se ordene alfabéticamente por la clave ([0] de cada tupla) ¿Cómo puedo hacer esto?
Solución
Ni la implementación líquida predeterminada ni las adiciones realizadas por Jekyll permiten lo que desea.
Me temo que lo que quieres simplemente no es posible con la configuración actual. Tendría que monkapatch jekyll o líquido para que los hashes devuelvan sus llaves en un orden ordenado.
Otros consejos
Esta es una vieja pregunta, pero solo paso el último tiempo en resolver esto por mí mismo. Usé el siguiente código para lograr lo que usted (y yo) queríamos.
{% 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 %}
¡También puedes usar matrices en lugar de hashes!
En lugar de usar este yaml:
categories:
a_category: category description
another_category: another category description
Puedes usar este:
categories:
- {name: 'a category', description: 'category description'}
- {name: 'another category', description: 'another category description'}
Y luego puedes iterar así, y el orden se conservará :)
{% for category in site.categories %}
<li>{{ category['name'] }}</li>
{% endfor %}
Índice de publicaciones por etiquetas ordenadas alfabéticamente (espacios no permitidos en los nombres de etiquetas):
{% 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 %}
Puede ordenar por la clave utilizando el siguiente método (que es compatible con las páginas GitHub):
{% 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 %}
Espero que esto ayude.
También quiero ser parte de esta competencia ofuscada (tipos, number_of_words
, ¿en serio?).
Este código está construyendo la etiqueta de la lista por etiqueta, buscando la siguiente etiqueta en orden lexicográfico en la lista en cada paso. Está en o (norte²) donde norte es el número de etiquetas.
<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>
Por cierto, los comentarios líquidos se ven absurdamente pesados.
Podrías ahorrarse algunos problemas y extender Liquid
:
- Puedes Crea tus propios bloques de etiquetas, y
- Puedes Crea tus propios filtros
p.ej
# 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)
Uso:
{{ myhash | keys | to_ul }}
Ejemplos:
# 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>"
Si te sientes afortunado, puedes mirar en Github el for.rb
archivo y extender el for
Sintaxis para manejar mejor los hash :).
Así es como solucioné el problema de 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 %}
Ahora cómo hacer que esto funcione con Haml ...