質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

3回答

6599閲覧

Rubyでの文字列置換について

sika_boze

総合スコア15

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

1グッド

2クリップ

投稿2016/02/28 08:21

Rubyにおいて、0始まりの数字は8進数と認識されてしまうので
013 → 13のように0を除去したいです。
今は以下のように01~09までの数字を置換する処理はをすべての場合を書いています。
そこでこの部分をまとめる方法、または効率の良い方法があれば教えていただけませんか?

よろしくお願いします!

ruby

1# 置換前の変数 2val = "010+025*078-05" 3 4#置換後のイメージ 5# val = "10+25*78-5" 6 7# まとめたい部分 8val = val.gsub("01","1") 9val = val.gsub("02","2") 10val = val.gsub("03","3") 11val = val.gsub("04","4") 12val = val.gsub("05","5") 13val = val.gsub("06","6") 14val = val.gsub("07","7") 15val = val.gsub("08","8") 16val = val.gsub("09","9")
DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

正規表現を使って、このようにしてはいかがでしょうか。

大雑把に説明すると、数字でない0or1文字、ゼロが1個以上、数字の連続、が見つかったら、「ゼロが1個以上」を除いたものに置き換えるようにしています。

ゼロは1つしか出てこないことを想定されていると思いますが、念のため、複数でも削除するようにしています。

lang

1val = "010+025*078-05" 2 3val.gsub!(/([^\d]?)0+(\d+)/, '\1\2') 4 5puts val # => 10+25*78-5

投稿2016/02/28 09:10

argius

総合スコア9388

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sika_boze

2016/02/28 13:54

回答ありがとうございます。 簡潔なコードな上にこちらの想定していなかった必要な処理(0が複数の場合)まで 含まれていてとても参考になりました! ちなみに以下の部分の"\1\2"はどのような処理になっているのでしょうか? val.gsub!(/([^\d]?)0+(\d+)/, '\1\2')
argius

2016/02/28 14:03

後方参照と呼ばれるものですね。 正規表現パターンの中で、カッコで囲んだ部分を置き換え時に参照できるものです。 このケースでは"0+"でマッチした部分以外は残す、という意味になります。 "+025*"の部分(2回目のマッチです)を例にとると、 ([^\d]?)の部分に "+"が、 0+の部分に "0"が、 (\d+)の部分に"25"がそれぞれマッチします。 "*"はここではマッチしません。 このようにマッチしたとき、"\1\2"は"+25"になります。 よって、この部分では"+025"を"+25"で置き換えることになります。 以上の処理が今回の例では4回繰り返されて、不要なゼロが除去されるというわけです。
sika_boze

2016/02/28 14:19

ありがとうございます。 つまり、"\1"などの後方参照は数字番目のカッコ部分を参照するということでしょうか?
argius

2016/02/28 14:43

> "\1"などの後方参照は数字番目のカッコ部分を参照するということでしょうか? はい、そのとおりです。 \0というのもあって、これはマッチした全体を指します。上の例では\0が"+025"になります。 ちなみに、他の言語(Perl,PHPなど)では、$1,$2...のように$記号を使うものもあります。
sika_boze

2016/02/28 15:32

最後まで細かい疑問にもお答えいただきありがとうございました! とてもわかりやすく非常に助かりました!
guest

0

000 は 0 にする,
0 は 0 のままとする、
0102 は 102 にするといった事も考慮する必要があります。
gsub を使った置換だけでも出来るのかもしれませんが、ちょっとしたメソッドを定義して対処してみました。
1.rb

ruby

1def normalize(str) 2 ans = '' 3 tokens = str.scan(%r!([\+\-\*\/]|\d+)!) 4 tokens.flatten.each do |token| 5 if token.length > 1 6 token.sub!(/^0*/, '') 7 token = '0' if token.length == 0 8 end 9 ans += token 10 end 11 ans 12end 13 14s = '010+025*078-05' # "10+25*78-5" 15p normalize(s) 16 17s = '10+25*78-5' # "10+25*78-5" 18p normalize(s) 19 20s = '0000+0102*03-0' # "0-102*3-0" 21p normalize(s)

実行結果

$ ruby 1.rb "10+25*78-5" "10+25*78-5" "0+102*3-0"

投稿2016/02/28 11:53

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sika_boze

2016/02/28 14:28

回答ありがとうございます。 こちらが意図していた挙動のプログラムのようです! サンプルもいくつか載せていただき理解しやすかったです。 ありがとうございました!
guest

0

勉強ついでに調べてみました。

問題の確認ですが、変数valに文字列として"010+025*078-05"が入っているので、
その中の数字の先頭の0を除去したいという質問でよろしかったでしょうか?

提示されているやり方では数字の中の0も除去してしまう恐れがあるため
危険です。
例)010203123

やり方としては文字列の

  1. 先頭の0を除去
  2. +0 の文字列の0を除去
  3. -0 の文字列の0を除去
  4. *0 の文字列の0を除去
  5. /0 の文字列の0を除去

となると思います。
それを順番にやると

val = val.sub(/^0/,'') # ここだけ sub を使用している事に注意 val = val.gsub(/\+0/,'+') val = val.gsub(/\-0/,'-') val = val.gsub(/\*0/,'*') val = val.gsub(/\/0/,'/')

....めんどくさいのでまとめちゃいましょう。

val = val.sub(/^0/,'').gsub(/\+0/,'+').gsub(/\-0/,'-').gsub(/\*0/,'*').gsub(/\/0/,'/')

もし、8進数にで格納されてしまった数字を単純に10進数にしたいだけなら、
013.to_s(8).to_i
(8進数をベースに文字列に変換して、10進数の数字に出力する)

でできます。

投稿2016/02/28 09:20

kurokoSin

総合スコア133

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sika_boze

2016/02/28 14:03

回答ありがとうございます! ご指摘の通り、数字中の0も取り除かれてしまい バグを含んでいたようでした。 ご指摘ありがとうございます。 他にも様々な注意点が詳しく解説されており 非常に参考になりました! ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問