実現したいこと
文字列にタグがあった場合、条件に応じてその前後にスペースを入れたいです。
具体例としては以下strを与え、タグの前後にスペースを入れて、後述する目的の結果を得たいです。
var ARR = [ {name:'食パン',id:1}, {name:'あんぱん',id:2}, {name:'ごまあんぱん',id:3} ]; const str = "こんにちは。食パンと#チーズケーキが食べたいです!あとごまあんぱんも!"; const result = get(str); console.log('result',result);
###目的の結果
基本的にタグの前後にはスペースを入れますが、条件は「『変数patternの正規表現で指定した文字列』がタグの前にあった場合は、タグの前にはスペースは入れない』というものです。
なので、patternとして『。』が指定されているために、「こんにちは。」の次にある「#食パン」の前にはスペースが入っておらず、それ以外のタグにだけスペースが入り以下をresultとして得たい考えです。
こんにちは。#食パン と#チーズケーキが食べたいです!あと #ごまあんぱん も!
発生している問題
resultが以下になってしまいます。つまりスペースを入れる位置が問題です。
こんにちは。#食パンと#チーズケーキが食べたいです!あと#ご まあんぱんも!
該当のソースコード
var ARR = [ {name:'食パン',id:1}, {name:'あんぱん',id:2}, {name:'ごまあんぱん',id:3} ]; const str = 'こんにちは。食パンと#チーズケーキが食べたいです!あとごまあんぱんも!'; const result = get(str); console.log('result',result); function get( str ){ let base_str = str; // タグリストをsortしてregにする let terms_name_arr = ARR.map( (el)=> el.name ); console.log('terms_name_arr',terms_name_arr); // あんぱんとごまあんぱんならごまあんぱんを優先させたいのでsortしておく terms_name_arr = terms_name_arr.sort(function(a, b) {return a.length < b.length;}); const reg = new RegExp( terms_name_arr.join('|'), 'g'); console.log('reg:',reg); // スペースを入れる位置 let posi_arr = []; // タグ化 str = base_str.replace(reg, function(match, offset, string) { console.log('match=「'+match+'」'); console.log('offset=「'+offset+'」'); // スペースを入れる位置 posi_arr.push( offset ); posi_arr.push( offset+match.length+1 ); // 先頭に#がついてなければ付与 if( base_str.substr(offset-1,1) === '#' ){ return match; }else{ return '#' + match; } }); // スペースを入れる console.log('posi_arr',posi_arr); posi_arr.forEach(function(posi,i){ // ループのたびにスペースが入ってstrの文字数が変わるから i を加算 const x = posi + i + 1; console.log('x=「'+x+'」'); // スペースを入れる位置で前後に分ける const before = str.slice(0, x); const after = str.slice(x); // タグの前後がpatternに一致しなければ、タグの前後にスペースを挿入 const pattern = /[##。、,!!]/g; const before_last = before.substr(-1, 1); // タグの直前の文字 console.log('before_last',before_last); let insert; if( before_last.match(pattern) ){ insert = ''; }else{ insert = ' '; } str = before + insert + after; }); // 一番最初のスペースだけ削除 return str.replace(/^\s+/,""); }
試したこと
「forEach」によって「str」が常に変化してしまうことが原因ではないかと考えています。
そしてスペースの挿入位置「x」を計算するときに、この「str」の変化を踏まえるべく「i」という値を加算しているのですが、それだけでは不備があるようです。
そこで「// スペースを入れなければ「i」を加算しない」という条件を付けてみたいのが以下ですが、このアプローチではうまくいきませんでした。
// スペースを入れる let add = true; console.log('posi_arr',posi_arr); posi_arr.forEach(function(posi,i){ // ループのたびにスペースが入ってstrの文字数が変わるから i を加算 let x; if(add){ x = posi + i + 1; }else{ x = posi + 1; } console.log('x=「'+x+'」'); // スペースを入れる位置で前後に分ける const before = str.slice(0, x); const after = str.slice(x); // タグの前後がpatternに一致しなければ、タグの前後にスペースを挿入 const pattern = /[##。、,!!]/g; const before_last = before.substr(-1, 1); // タグの直前の文字 console.log('before_last',before_last); let insert; if( before_last.match(pattern) ){ insert = ''; add = false; // スペースを入れなければ「i」を加算しない }else{ insert = ' '; add = true; } str = before + insert + after; });
その他、ご覧のようにコンソールを出しながら、あれやこれやとスペースを入れる「x」の位置を調整しようと試しているのですが、あちらを調整すればこちらがズレる、という繰り返しをもう今朝から100回くらい重ねておりまして…
途方にくれておりましたところ、質問サイトの利用に思い至りました。
補足情報(FW/ツールのバージョンなど)
特にバージョン情報は関係ないかと思いますが、jQueryは最新の3.4での方法でお願いできましたら幸いです。
何卒、宜しくお願いいたします。
回答1件
あなたの回答
tips
プレビュー