アイテムにつけられたタグを重複なく出力する

MTQに、「アイテムに付けられたタグの一覧表示」という質問が上がっていました。
すべてのアイテムにつけられたタグを、重複しないように出力したいという内容です。
この質問に答えてみます。

1.問題点

質問された方は、以下のようなテンプレートを組まれていました。

<mt:Assets>
<mt:AssetTags glue=" | ">
<$mt:TagName$>
</mt:AssetTags>
</mt:Assets>

この書き方だと、アイテムを順に1つずつ読み込み、アイテムごとにつけられたタグを出力する形になります。
そのため、複数のアイテムに同じタグがつけられていると、それらが重複して出力されます。

例えば、写真Aには「赤,きれい,花,ポップ」というタグがあり、写真Bには「緑,華やか,葉っぱ,ポップ」というタグがつけられているとします。
この状況で、上記のテンプレートでタグを出力すると、まず写真Aのタグが順に出力され、次に写真Bのタグが順に出力されます。
そのため、以下のように「ポップ」が重複します。

赤 | きれい | 花 | ポップ | 緑 | 華やか | ポップ | 葉っぱ

2.ハッシュで重複するデータを除く

この例のように、たくさんのデータの中から、重複するものを取り除きたいということは、よくあります。
この処理は、ハッシュの使い道の中でも特に典型的なものです。

たくさんあるデータから、重複するものを取り除くには、キーが個々のデータで、値が1になるようなハッシュを作ります。
そして、ハッシュを作り終わったら、そのハッシュのキーを出力します。

上の例だと、写真Aのタグから、ハッシュは以下のような状況になります。

キー
1
きれい1
1
ポップ1

次に、写真Bのタグを、上記のハッシュに追加していきます。
「緑」「華やか」「葉っぱ」まで追加すると、ハッシュは以下のようになります。

キー
1
きれい1
1
ポップ1
1
華やか1
葉っぱ1

そして、写真Aと写真Bで重複する「ポップ」のタグを、上記のハッシュに追加します。
この場合、キーが「ポップ」の要素はすでに存在していますので、その要素を上書きすることになります。
したがって、ハッシュの内容は上のままで変化しません。

最後に、上記のハッシュから、キーだけを取り出して、出力します。
これで、重複する「ポップ」を1つにまとめて出力することができます。

3.テンプレートの組み方

ここまでの話に沿って、テンプレートを組むと、以下のようになります。

<mt:Assets>
  <mt:AssetTags>
    <$mt:TagName setvar="tag_name"$>
    <$mt:SetVar name="asset_tags" key="$tag_name" value="1"$>
  </mt:AssetTags>
</mt:Assets>
<mt:Loop name="asset_tags" glue=" | ">
  <$mt:GetVar name="__key__"$>
</mt:Loop>

前半のMTAssetsタグのブロックが、アイテムにつけられたタグをハッシュに格納する処理です。
1/6行目のMTAssetsタグですべてのアイテムを順に読み込み、そして2/5行目のMTAssetTagsタグでアイテムごとのタグを読み込みます。
3行目では、個々のタグの名前を、「tag_name」という変数に代入します。
そして、4行目では、「asset_tags」という名前のハッシュで、キーが変数tag_name(=アイテムのタグ)になっている要素に、値として1を代入します。

一方、後半のMTLoopタグのブロックが、タグの一覧を出力する部分です。
7/9行目のMTLoopタグで、ハッシュasset_tagsから要素を順に取り出します。
そして、8行目のMTGetVarタグで、取り出した要素のキー(__key__)を出力します。

4.変数(配列/ハッシュも含む)は必須

Movable Type 5.1 Webサイト製作ガイドVolume 2この例のように、手の込んだ処理をしようとすると、変数や、その応用である配列やハッシュを、避けて通ることができません。
拙著「Movable Type 5.1 Webサイト製作ガイドVolume 2」では、変数および配列/ハッシュについて、かなり詳しく解説しています。
「変数や配列/ハッシュがよく分からない」という方は、ぜひ拙著をお読みください。