質問: ハッシュタグ機能を実装しようと考えており、 第一歩のクライアント側の実装として、投稿の中から「#」が含まれるか判別し、ハッシュタグの部分の文字列をリンク化したコードをjQueryで書いてみましたが、どうしても無理やり感があり、実装のアプローチにもっと良い手段があるかもしれないと考え、投稿させていただきました。 よりスマートな書き方の発想があればぜひフィードバックいただけると嬉しいです。 既存コードの方針としては以下です。 1.投稿にハッシュタグにあたる文字「#」があるか調べる 2.あれば#の数だけ文字列を分割する 3.分割したあと、リンク化する部分はリンク化し、そうでないものはそのまま 4.htmlとしてappendする ``` 何も入力せずに送信ボタンをクリックして下さい 送信 ``` ``` ```
回答: どの部分に無理矢理感を感じられているのかわかりませんが、文字列のパース部分だと解釈して、回答させていただきます。意図に反した回答でしたら申し訳ありません。 もともと文字列のパースは、何らかのライブラリを使わない限りは愚直にやるしかないと思うので、提示されているロジックで解析処理を行う形でよいのではないかと思います。 その上で私が書くとしたら、以下のようなコードになるかなと思います。 基本の解析ロジックは一緒ですが、mapとjoinを利用して、メソッドチェインのような形で文字列を順番にパースしています。関数型っぽい書き方ですね。もしかするともっと簡潔な書き方があるかもしれません。 最近のJavaScriptではこのような書き方はよく見られるので、JavaScriptでやるならこういう書き方のほうが良いかなと思います。(もちろん掲示されているコードが間違っているわけではないので、好みの問題だとは思います) 特に、今回のように文字列を解析して変換する処理においては、`split(特定の記号で文字列を分割して配列にする)` → `map(配列要素一個一個に対して、同じ処理を適用)` → `join(配列を再び文字列に結合する)` の流れはかなり便利なので、覚えておくと役に立つと思います。 (サンプルコードでは`str.split().map().join()`のメソッドチェーンが使われているのがわかるかなと思います) ちなみにサンプルコードでは、タグであるという認識を[#]の有無ではなく「 #」の有無で判定しています。これにより、頭に空白がない#がタグ化されなくなり、#タグの中にスペースなしの#があっても普通の文字として認識されるようになります。 とりあえず、文字列をパースしている部分のコードだけ載せておきます。 提示されているコードで使うのであれば、以下のように使えば変換してくれると思います ``` let val = $('#txt').val(); const result = addAnchrInTag(val) ``` ``` //Twitterのように投稿から投稿からハッシュタグが含まれるものをリンクに変えるコードのhtml、JSのみ //一つの投稿に #がついている文字列は、スペースが空くかそれ以降何もないとハッシュタグとみなされる //ハッシュタグとみなされた投稿は#から終わりまで、リンク(#文字列)で囲まれる //一つの投稿はいくつでもハッシュタグを持てる /** * ハッシュタグがあれば、そのハッシュタグ部分をリンクにした文字列を返す * @param {string} 文字列 * @return {string} タグ部分がurl化された文字列 */ function addAnchrInTag(str){ return str.split(' #').map( (s,i) =>{ if (i === 0 && s.indexOf('#') === -1){ // split後の先頭の文字はurl化しない return s } else if (i === 0 && s.indexOf('#') === 0){ // 文章の頭のタグはそのままurl化 return addAnchr(s) } // 文章の途中にあるタグは#が取り除かれているので、#をつけ直してurl化 return addAnchr('#' + s) }).join(' ') } /** * 引数に指定した文字列にリンクを付けて返す * スペースが存在する場合は最初のスペースが現れる前までをリンク化する * @param {string} 文字列 * @return {string} スペースが現れるまでをurl化した文字列 */ function addAnchr(str){ return str.split(' ').map( (s, i) => { if (i === 0){ return `${s}`; } return s }).join(' ') } // ここから実行例 let sampleArr = ["xx #xyz #ほげほげ ふがふが", "こんにちは! #hello", "お世話になっております", "#React.js #JavaScript #エンジニア #デザイナー", "#タグの中に#があるよ!! #タグ 文章"]; const result = sampleArr.map( str => addAnchrInTag(str)) console.log(result) // => [ 'xx #xyz #ほげほげふがふが','こんにちは! #hello','お世話になっております','#React.js #JavaScript #エンジニア #デザイナー',' #タグの中に#があるよ!! #タグ','文章' ] ```