5

Is there way to match strings in scala like this:

  def matcher(arg: String) : Expr = {
    case left :: '*' :: right => new Binary("*", left, right)
    case left :: '+' :: right => new Binary("+", left, right)
  }

where left and right are have type String?

1
  • Are left and right of fixed length? Commented Oct 10, 2015 at 12:42

3 Answers 3

9

You can achieve your goal by matching on regular expressions.

trait Expr

case class Binary(op: String, leftOperand: String, rightOperand: String) extends Expr

val mulPattern = "(\\d*)\\*(\\d*)".r
val addPattern = "(\\d*)\\+(\\d*)".r

def matcher(arg: String) : Expr = {
  arg match {
    case mulPattern(left, right) => new Binary("*", left, right)
    case addPattern(left, right) => new Binary("+", left, right)
  }
}

def main(args: Array[String]): Unit = {
  println(matcher("1+2")) // Binary("+", "1", "2")
  println(matcher("3*4")) // Binary("*", "3", "4")
} 
Sign up to request clarification or add additional context in comments.

2 Comments

could make a method to create those patterns, maybe like this: def binRegex(symbol: Char) = raw"""([^$symbol]+)[$symbol]([^$symbol]+)""".r
Thanks for your answer, sir!
2

I don't think so.

You might be able to do it, if you convert the String into a List or Vector of Char and then revert the results with mkString. But I haven't be able to come up with something.

However, imo, a regular expression would be more concise and readable:

trait Expr

case class Binary(op: String, left: String, right: String) extends Expr

val Expression = """(.*?)\s*([+-\/\^\*])\s*(.*)""".r
def matcher(arg: String) : Expr = arg match {
  case Expression(left, op, right) => new Binary(op, left, right)
}

val test = matcher("a + b")
val test2 = matcher("a * b")

Comments

1

You can also do this with extractors:

object Mult {
  def unapply(x: String): Option[(String, String)] = x.split("\\*") match {
    case Array(a: String, b: String) => Some(a -> b)
    case _ => None
  }
}

object Add {
  def unapply(x: String): Option[(String, String)] = x.split("\\+") match {
    case Array(a: String, b: String) => Some(a -> b)
    case _ => None
  }
}

def matcher(arg: String) = arg match {
    case Mult(left, right) => Binary("*", left, right)
    case Add(left, right) => Binary("+", left, right)
    case _ => println("not matched")
 }

You may also want to implement apply method for each extractor like:

def apply(l: String, r: String) = s"$l*$r"

but this is not mandatory

1 Comment

Seems like your solution suited me the most, thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.