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

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

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

ScalaはJava仮想マシンで動作を行うオブジェクト指向型プログラミング言語の1つです。静的型付けの関数型言語で、コンパイルエラーの検出に強みがあります。

Q&A

解決済

2回答

1133閲覧

複数括弧の処理について

colorful

総合スコア23

Scala

ScalaはJava仮想マシンで動作を行うオブジェクト指向型プログラミング言語の1つです。静的型付けの関数型言語で、コンパイルエラーの検出に強みがあります。

0グッド

0クリップ

投稿2019/01/29 01:39

編集2019/01/29 01:42

こんにちは。

scalaのことで質問したく、投稿しました。

キーボードから入力した文字列の左端に複数の開き括弧がある場合、その開き括弧に対応する閉じ括弧と一緒に削除したいと考えております。どのような処理を使ったらよいのか教えていただけないでしょうか?
処理の内容としては以下のことを考えています。

実現したい例1
入力した文字列:((ab(c)))
出力したい文字列:ab(c)

実現したい例2
入力した文字列:(((abc(d)))
出力したい文字列:abc(d)

現在の処理結果
入力した文字列:((ab(c)))
出力結果:(ab(c))
と、現在は1組の括弧しか消せない状態です。

現在のプログラムの内容
code:String

if(code.head=='('&&code.tail==')'){
code = code.replaceAll("^((.+))$", "$1")
}

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

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

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

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

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

guest

回答2

0

ベストアンサー

ワンライナー

Scala

1def unParentheses(s:String):String = if (!s.isEmpty && s.head == '(' && s.last == ')') unParentheses(s.drop(1).dropRight(1)) else s

パターンマッチ

Scala

1def unParentheses(s:String):String = { 2 def up(c: List[Char]):List[Char] = c match { 3 case Nil => Nil 4 case '('::xs if !xs.isEmpty && xs.last==')' => up(xs.dropRight(1)) 5 case _ => c 6 } 7 up(s.toList).mkString 8}

どちらも空文字列のガードが入るので美しくありません。実行は以下のとおり。

Scala

1unParentheses("") 2unParentheses("(") 3unParentheses(")") 4unParentheses("()") 5unParentheses("((ab(c)))") 6unParentheses("(ab(c))") 7unParentheses("ab(c)")

命令型から関数型へ

質問の意図は、Javaで書けるプログラムをScalaにしかっただけでしょうか。以下が望んでいる答えです。"()"の無限ループを避けるため正規表現を変更しました。せっかくなので、これをScalaの関数型プログラミングに変形します。

Scala

1def unParentheses(code:String):String = { 2 var term = code.slice(0,code.length) 3 while(!term.isEmpty && term.head =='(' && term.last == ')'){ 4 term = term.replaceAll("^\((.*)\)$", "$1") 5 } 6 term 7}

上の命令型ロジックの構造を変えます。

  • var term を削る。必要ないため。
  • whileの代わりに末尾再帰にする。末尾再帰はwhileと実質的に同じです。

Scala

1@scala.annotation.tailrec 2def unParentheses(code:String):String = { 3 if (code.isEmpty || code.head !='(' || code.last != ')') 4 code 5 else 6 unParentheses(code.replaceAll("^\((.*)\)$", "$1")) 7}

この if else 構造を、波括弧をはずして一文にすると、ワンライナーになります。

Scala

1@scala.annotation.tailrec 2def unParentheses(code:String):String = if (code.isEmpty || code.head !='(' || code.last != ')') code else unParentheses(code.replaceAll("^\((.*)\)$", "$1"))

投稿2019/01/29 10:56

編集2019/01/30 09:40
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

colorful

2019/01/29 11:35

回答していただき、ありがとうございました。 おかげさまで、助かりました。
colorful

2019/01/30 11:41

回答していただき、ありがとうございます。 今回、Scalaで括弧処理を行っていて本箇所でつまづいてしまい質問させていただきました。 無事に解決しました。ありがとうございました。
guest

0

String#tail最初の1文字以外を取得するメソッドです。
最後の文字だけ取得したい場合はString#lastを使います。

[追記]
括弧が複数ある場合を忘れてました。

ifではただの真偽値の判定なので、whileで繰り返すなどの工夫が必要です。

投稿2019/01/29 08:12

編集2019/01/29 09:33
dice142

総合スコア5158

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

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

colorful

2019/01/29 09:28

回答していただき、ありがとうございます。 if(code.tail=='('&&code.last==')')として、for文かwhile文で左端に括弧がなくなるまで回したほうが良いのでしょうか?
dice142

2019/01/29 09:33

すみません、「1回しかできない」という部分を失念してました。 回答に追記しましたが、概ねその方法で良いはずです。
dice142

2019/01/29 09:34 編集

ただ、左括弧だけより、両端を判定した方が無駄にreplace処理が発生しなくて良い気がします。
colorful

2019/01/29 09:45

なるほど、ありがとうございます 一度、作成してみたいと思います。
dice142

2019/01/29 09:50

ちなみに、「(a)(b)」のようなことは想定してないです。
colorful

2019/01/29 10:08

分かりました。 ありがとうございます。
colorful

2019/01/29 11:38

while文で試してみたのですが、エラー表示がなく、実行はできるのですが全く動かない感じです。 どこが悪かったのか、ご指摘いただけないでしょうか? code:String var term = code.slice(0,code.length) while(code.head =='(' && code.last == ')'){ term = code.replaceAll("^\((.+)\)$", "$1") }
dice142

2019/01/29 13:49

そもそもcodeに値が入っているのか、while文には入っているかなど、 println()やコメントアウトを使いながら試してみてください。
colorful

2019/01/30 00:00

なるほど、ありがとうございます。 確認しながら、試してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問