ひとつのやり方としては、各ランキングアイテムのCSSクラスであるranking1
, ranking2
... といった文字列をキーにして出現回数を値とするMapでカウンターを作ることです。
この回答では質問にあるコード
$('.ranking1').each(function(){
$(this).prepend('<span class="num">' + i + '</span>');
i++;
});
$('.ranking2').each(function(){
$(this).prepend('<span class="num">' + i2 + '</span>');
i2++;
});
・・・
から推測されるHTMLとして以下
html
1<ul>
2<li class="ranking3">あいうえお</li>
3<li class="ranking1">かきくけこ</li>
4<li class="ranking4">さしすせそ</li>
5<li class="ranking1">たちつてと</li>
6<li class="ranking3">なにぬねの</li>
7<li class="ranking1">はひふへほ</li>
8<li class="ranking4">まみむめも</li>
9<li class="ranking2">やゆよ</li>
10<li class="ranking1">らりるれろ</li>
11<li class="ranking2">わをん</li>
12</ul>
を想定して、Mapを使う具体的なやり方の一例を挙げていきます。なお上記のHTMLはMapを使う説明のために必要最低限の簡易なものです。(※CSSクラス指定がより複雑な場合の対応を回答の末尾に追記しました。)
欲しいのは 'ranking1'
, 'ranking2'
... といった文字列を与えるとそれのカウント数を返してくれる関数です。ですので、まずそのような関数を作って返してくれる(高階)関数makeCounter
:
javascript
1function makeCounter() {
2 const map = new Map;
3
4 return (key) => {
5 const count = 1 + (map.get(key) || 0);
6 map.set(key, count);
7 return count;
8 }
9}
を作っておきます。次にこれを実行して返される関数を変数 countOf
に代入しておきます:
javascript
1const countOf = makeCounter();
この countOf
は関数であり引数にCSSクラス名の ranking<数字>
の文字列を渡すことで各ランキング別の出現順を表す1, 2, 3 ・・・の番号を得ることができます。これを使って、全ランキングアイテムを取ってきてそれらの各々に順位表示のspan
を prepend するのは以下のように書けます。
javascript
1$('[class^=ranking]').each(function() {
2 const count = countOf($(this).attr('class'));
3 const span = $('<span>').text(count).attr('class', 'num');
4 $(this).prepend(span);
5});
Mapをカウンターとして使うこのやり方のメリットとしては、ランキングの種類が今後増えても全ランキングアイテムを取得してループするのでランキングの種類が増えるだけの変更に対しては修正は不要になることです。またランキングの種類が何種類あるのか(つまりクラス ranking<数字>
の <数字>
の最大値は何か)を知っている必要もありません。
追記
もし、各ランキングアイテムの class が
html
1<li class="up ranking4">さしすせそ</li>
だったり
html
1<li class="ranking4 down">さしすせそ</li>
などのように、ranking<数字>
以外のクラスも入ってくることがあり得る場合は上記のコードはそのままでは使えません。この場合は ranking4
であれば CSSクラスのほうは ranking
のみにして 4
をdata-*属性で指定することにして、たとえば
html
1<li class="up ranking" data-ranking-id="4">さしすせそ</li>
といったように修正したうえで、$('.ranking')
で取れる各要素の data-ranking-id
属性値をキーとして先述のカウンターを使えばよいかと思います。