つい最近の仕事でページに記載されているリストを50音順に並び変えたいという要望がありました。
例としては以下のような感じです。
data-name属性にそれぞれのローマ字読みの値をセットします。この値を基準に並び替えをしていきます。
<ul class="myList">
<li data-name="kimura">木村</li>
<li data-name="aizawa">相澤</li>
<li data-name="tanaka">田中</li>
<li data-name="ueda">上田</li>
<li data-name="itou">伊藤</li>
</ul>
<!-- /↓以下のように並べ替えたい -->
<ul class="myList">
<li data-name="aizawa">相澤</li>
<li data-name="itou">伊藤</li>
<li data-name="ueda">上田</li>
<li data-name="kimura">木村</li>
<li data-name="tanaka">田中</li>
</ul>
それぞれのdata属性の持つ値を配列に格納する
配列を操作するメソッドがJavascriptにはいろいろありますが、「sort」という並び替えを実現するメソッドもあります。
このsortメソッドは配列を操作するメソッドなのでまずは、各<li>タグのdata-name属性の値を配列にセットするというところから始めます。
//data-name属性の値を取得
var kana = $('.myList li').map(function(){
return $(this).data('name');
});
//配列に保存
var kana = kana.toArray();
console.log(kana); // (5) ["kimura", "aizawa", "tanaka", "ueda", "itou"]
ソートしてみる
kana.sort();
console.log(kana); // (5) ["aizawa", "itou", "kimura", "tanaka", "ueda"]
実現したい並びと違うのがわかると思います。
これはアルファベット順に並んでいますね。これをどうにかしてローマ字の順番に並べるにはどうしたらよいか…?
独自のソートルールを作る
ローマ字を基準に並び替えをするルールは見当たらなかったので、自分でルールを作ってしまいます。
日本語の発音をローマ字に直した値を変数に定義します。
今回母音以外を最初の2文字に限定したのは3文字目まで入れると配列に入れる要素数がとてつもない数になるからです。
2文字目までだけでも重複はないので、正しくソートすることができます。
const orderRule = ['a','i','u','e','o','ka','ca','ga','ki','ky','gi','gy','ku','cu','gu','ke','ge','ko','co','go','sa','za','jy','ja','ju','jo','sh','si','ci','zi','ji','ja','sh','su','zu','se','ce','ze','so','zo','ta','da','ti','ch','ty','ji','di','ts','tu','zu','du','te','de','to','do','na','ni','ny','nu','ne','no','ha','ba','pa','hi','bi','hy','by','py','pi','hu','pu','bu','he','be','pw','ho','bo','po','ma','mi','my','mu','me','mo','ya','yu','yo','ra','ri','ry','ru','re','ro','wa','wo'];
先ほど定義した変数kanaには以下の要素がセットされています。
[“kimura”, “aizawa”, “tanaka”, “ueda”, “itou”]
これを独自のルールに照らし合わせるために、[“ki”, “a”, “ta”, “u”, “i”]という形で保存できるように配列の中身を調整します。
独自ルールに基づいた形に配列を修正
今回作成した独自ルールは母音は1文字、それ以外は最初の2文字の文字要素でできています。
なので、[“ki”, “a”, “ta”, “u”, “i”]という形の配列にしたいと思います。
//data-name属性の最初の1文字(母音の場合)or2文字を取得
var kana = listElm.map(function(){
var firstLetter = $(this).data('name').slice(0,1);
if(firstLetter === 'a' || firstLetter === 'i' || firstLetter === 'u' || firstLetter === 'e' || firstLetter === 'o' ) {
return $(this).data('name').slice(0,1);
}
else {
return $(this).data('name').slice(0,2);
}
});
//配列に保存
var kana = kana.toArray();
console.log(kana); // (5) ["ki", "a", "ta", "u", "i"]
独自のルールでソートしてみる
kana.sort(function(a, b) {
if (orderRule.indexOf(a) > orderRule.indexOf(b)) return 1;
if (orderRule.indexOf(a) < orderRule.indexOf(b)) return -1;
return 0;
});
console.log(kana); // (5) ["a", "i", "u", "ki", "ta"]
先ほどとは違って、希望通りローマ字の順で並び替えができました。