JavaScriptのmapやreduceは実用言語っぽい挙動で自分のようなぬる者にはありがたいよね〜のシリーズの第4弾です。
といいつつ、ある素材について、いざやってみるとfilterやreduceはおろか、メインロジック部分あたりではmapさえも使わなかったので、実際は、filterやreduceでおしゃれにコーディングできそうな雰囲気があるテーマについて、筆者の棋力ではそうはならなかったけど、そこそこスニペットとして面白かったので、公開してみました...という読み替えでお願いします。
とりあつかっているもの
- 漢字表記とカナ読みの固有名詞的なワードの組み合わせがあり、カナでない部分に読みを当てたトークンを生成
- 自作の照合型ソートの例
1がこりゃ面白いかもと思って始めたものの力技(というかナイーブな例)になってしまったので、記事にするには不足かなと思って、2も対応してみましたが、手グセで、2の方もナイーブな例となりました。 (ですが、書捨てるには惜しい気がしたので自分メモとして残しています。)
1. 漢字表記とカナ読みの固有名詞的なワードの組み合わせがあり、カナでない部分に読みを当てたトークンを生成
コード例
'use strict'; const a = 'ブラックJARKSニ世露死苦メカドッグ'.split(''); const bStr = 'ブラックジャックスニヨロシクメカドッグ'; const k = 0x30A1; const kana = [...Array(92).keys()].map(i => String.fromCodePoint(k + i)); //const hiragana = [...Array(86).keys()].map(i => String.fromCodePoint(0x3041 + i)); console.log(kana); const isKana = c => kana.includes(c); const tokenize = a => { let c = a.shift(); let p = c; const s = [p]; while (a.length > 0) { c = a.shift(); s.push( (isKana(c) && !isKana(p)) || (!isKana(c) && isKana(p)) ? ',' + c : c ); p = c; } return s.join('').split(','); }; const tokens = tokenize(a); const getReadingForm = (tokens, bStr) => { const k2k = {}; let str = bStr; for (let i = 0; i < tokens.length; i++) { const t = tokens[i]; const kanaTknStsPos = str.indexOf(t); if (kanaTknStsPos < 0) { continue; } if (kanaTknStsPos === 0) { str = str.slice(t.length); continue; } const kanjiYomi = str.slice(0, kanaTknStsPos); k2k[tokens[i - 1]] = kanjiYomi; str = str.slice(kanaTknStsPos + t.length); } return k2k; } console.log(getReadingForm(tokens, bStr));
実行結果
{ JACKS: 'ジャックス', '世露死苦': 'ヨロシク' }
漢字と読み(例では変数 aとbStr)を前の方から比較して、同じカナが現れるまでは漢字(やアルファベットなど)と読みのペアとみなして、走査するイメージです。
ある前提のもと、diffっぽいことをナイーブなやり方で実施するイメージでしょうか。
2. 自作の照合型ソートの例
実際は難しいことはしておらず、Array.sort関数に、照合表で勝ち負けを参照しながら、並びを判定する関数を引き渡しして実現します。
'use strict'; const collationfunc = (a, b) => { const co = [...'abcdefghijklmnopqrstuvwxy'].reverse(); //照合用の配列。zはあえて無し。 console.log(co); const ia = co.findIndex(e => e === a); const ib = co.findIndex(e => e === b); //どちらも存在しない場合は昇順 if (ia === -1 && ib === -1) return a > b ? 1 : -1; //一方が存在しなければ、もう一方の存在する方の勝ち if (ia === -1) return 1; if (ib === -1) return -1; //照合の優先度が高い方が勝ち if (ia > ib) return 1; if (ia < ib) return -1; }; const sorted = ['a', 'b', 'g', 'd', 'z', 'zzzz', 'f'].sort(collationfunc); console.log(sorted); /* ↓ 期待値イメージ zをのぞく1文字アルファベットは降順。それ以外(zとzzzz)は最後尾となりこの2つの間はアルファベットの昇順。 [ 'g','f','d','b','a','z','zzzz' ] */