プロが教える店舗&オフィスのセキュリティ対策術

ary を rst のように変換してみたいのです。
いろいろなアルゴリズム(アイディア)があったら教えてください。
できるなら、より洗練されたやつをお願いします。

let ary = [
'',
'1 丁目',
'1 丁目 2 番地',
'1 丁目 2 番地 3 号',
' 1丁目 ',
' 1丁目 2 番地 ',
' 1丁目2番地 3 ',
'1',
'1-2',
'1-2-3',
'2 番地', // ×
'2 番地 3 号', // ×
'-2-3'// ×
];

let rst = [
[1],
[1,2],
[1,2,3],
[1],
[1,2],
[1,2,3],
[1],
[1,2],
[1,2,3]
];

A 回答 (6件)

洗練された、というのがどういう意味か不明ですが


こういうのは地道にやっていく方が、メンテナンス性も上がって良いと思います。

空の配列rstを用意
aryの各文字列について以下を実施
 1.「番地」が含まれている、かつ、「丁目」が含まれていない場合はエラー
 2. 文字の置換
  2-1 ' '(空白)を''(空文字)に置換 // 空白の削除
  2-2 '丁目' と '番地'を '-' に置換
  2-3 '号' を''(空文字)に置換 // '号'の削除
 3. 分割
  3-1 2.でできた文字列の最初が '-' ならエラー // '-2-3'の場合
  3-2 文字列を'-'で分割(split)して配列にする
 4. 数値化
  配列の各要素を文字列から数値に変換する
 5. 生成された配列をrstに追加(push)する(エラーだった場合は何もしない)
    • good
    • 0
この回答へのお礼

回答、有難うございます。手順を追って作ってみました。(正規表現不使用)
「文字列の最後が "-" になる場合、それを削除する。」が分割の前に必要でした
>>>洗練された
単純なショートコーディングではなく、ロジックのショートコーディングみたいな?


let rst = [ ];
for (let t of ary) {
 try {
  if ('' === t)
   throw new Error;

  if (-1 < t.indexOf ('番地'))
   if (-1 === t.indexOf ('丁目'))
    throw new Error;
  
  t = t.split (' ').join ('');
  
  t = t.split ('丁目').join ('-');
  t = t.split ('番地').join ('-');
  t = t.split ('号').join ('');
  
  if (0 === t.indexOf ('-'))
   throw new Error;
  
  //ここ3行追加
  let last = t.length - 1;
  if (t.lastIndexOf('-') === last)
   t = t.substr (0, last);
  
  let tmp = t.split ('-');
  
  tmp = tmp.map (a => parseInt (a, 10));
  
  rst.push (tmp);  
 }
 catch (err) {
  ;
 }

}

console.log (rst);

お礼日時:2018/03/28 08:48

''の場合が抜けていました。



0. ''(空文字)だったらエラー  を追加です。
    • good
    • 0

例えばこう


<script>
var a=[
'',
'1 丁目',
'1 丁目 2 番地',
'1 丁目 2 番地 3 号',
' 1丁目 ',
' 1丁目 2 番地 ',
' 1丁目2番地 3 ',
'1',
'1-2',
'1-2-3',
'2 番地', // ×
'2 番地 3 号', // ×
'-2-3'// ×
];

var reg=new RegExp('^\\d+(-\\d+){0,2}$|^\\d+丁目((\\d+番地)+(\\d+号*)*)*$');
for(var i=0;i<a.length;i++){
console.log(a[i]+(a[i].replace(/\s/g,"").match(reg)?"ok":"ng"))
}
</script>

まずは整合性のチェックだけする。あとはこれにマッチした場合数値だけ抜き出せばOK
<script>
var a=[
'',
'1 丁目',
'1 丁目 2 番地',
'1 丁目 2 番地 3 号',
' 1丁目 ',
' 1丁目 2 番地 ',
' 1丁目2番地 3 ',
'1',
'1-2',
'1-2-3',
'2 番地', // ×
'2 番地 3 号', // ×
'-2-3'// ×
];
var reg=new RegExp('^\\d+(-\\d+){0,2}$|^\\d+丁目((\\d+番地)+(\\d+号*)*)*$');
var b=a.map(function(x){
return x.replace(/\s/g,"").match(reg)?x.match(/\d+/g):null;
}).filter(function(x){
return x!=null;
});
console.log(b);
</script>
    • good
    • 0
この回答へのお礼

回答、有難うございます。

問いの例題に "1丁目2-3"を加えるべきでした。

最近、作るまでのコスト、動かしているときのコスト、メンテナンスせざるを得ないときのコストを考えるようにもなりました。(波型インデントにコストをかけているのでは?という突っ込みは無しで)

回答頂いた例は、正規表現を使って整形をし、パターンを調べ、抽出をしています。(三回も!)
正直に言えば一回で可能ですよね。^^;

ところで、普段の回答ではどこにコストをかけます?


/^\s*(\d+)(?:\s*(?:丁目|\-)(?:\s*(\d+)(?:\s*(?:番地|\-)(?:\s*(\d+)(?:\s*号?)?)?)?)?)?\s*$/.exec (str);

つまり、
console.log (
ary.map (a => /^\s*(\d+)(?:\s*(?:丁目|\-)(?:\s*(\d+)(?:\s*(?:番地|\-)(?:\s*(\d+)(?:\s*号?)?)?)?)?)?\s*$/.exec (a))
.filter (a => !! a)
.map (([,...a]) => a.filter (a => !! a).map (a => parseInt (a, 10)))
);

お礼日時:2018/03/28 13:57

「1丁目2-3」がOKとなるとまたちょっと微妙ですね


(?:丁目|\-)・・・(?:番地|\-)とすると
結局1-2番地3とかヒットしちゃうのでパターン分けが
煩雑になるとおもいまいすよ

抜き出すのは数値と決まっていて取り出し方は\dを拾う方が圧倒的に楽なので
今回の肝はあくまでマッチさせられるかどうかです
    • good
    • 0
この回答へのお礼

そこは、正規表現を書いてくれないんですね。^^;

いつも参考にさせて頂いております。
今後ともよろしくお願いします。
(わざわざ書かなくて・・・)

お礼日時:2018/03/30 09:45

No.1です。


一つ処理が抜けていて失礼いたしました。やはり実際に動作させてみないと漏れがでますね。

私はJavaScriptのコードはあまり詳しくないのですが回答いただいたコードで気になった点です。
・try~catch~とthrow new Error;の部分は単純に (for に対する) continue方が良くないでしょうか?
 (最初の回答でエラーと書いてしまったのが良くなかったです)
・置換はreplaceを使用したほうが分かりやすいのではないでしょうか?

意図があって、その様にされているのでしたら申し訳ありません。
    • good
    • 0
この回答へのお礼

>一つ処理が抜けていて
問題なしですよ!私の回答するときなどは、そりゃぁ〜もう抜けまくってますから。
もしこれからの人がロジックを見たときに、理解しやすいようにしました。
(それにちょっと「できる奴!」に見えるから)

>置換はreplaceを使用したほうが分かりやすい
確かにそうですね。半角空白を置き換えるときに、/¥s/g だと正規表現を使うことになります。
それが嫌でした。(なんとか使わない方向で)
JSの置き換えは、第1引数が文字列の場合1回だけしか行われません。その対策が面倒です。
(それにちょっと「できる奴!」に見えるから)

ついつい正規表現に頼ってしまいがちですね。
面倒なくらい長い正規表現を書いておきながなんですけどね。
(それはちょっと「できる奴!」に見えるから)

ありがとうございました。

お礼日時:2018/03/30 09:39

#4です、解決していたわけではないのですね


<script>
var a=[
'2丁目3',//OK
'3丁目4-5',//OK
'4丁目5-6号',//これが通っちゃいます、抜きますか?
'5-6番地', //NG
'',
'1 丁目',
'1 丁目 2 番地',
'1 丁目 2 番地 3 号',
' 1丁目 ',
' 1丁目 2 番地 ',
' 1丁目2番地 3 ',
'1',
'1-2',
'1-2-3',
'2 番地', // ×
'2 番地 3 号', // ×
'-2-3',// ×
];
var reg=new RegExp('^\\d+(-\\d+){0,2}$|^\\d+丁目((\\d+(番地|-)*)+(\\d+号*)*)*$');
var b=a.map(function(x){
return x.replace(/\s/g,"").match(reg)?x.match(/\d+/g):null;
}).filter(function(x){
return x!=null;
});
console.log(b);
</script>
    • good
    • 0
この回答へのお礼

ありがとうございます

お礼日時:2018/03/31 13:18

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!