2015-10-10 6 views
5

Есть ли способ сопоставления строк в Скале, как это:Scala, сопоставление с образцом, строки

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

, где слева и справа будут иметь тип String?

+0

Имеются ли левые и правые фиксированной длины? –

ответ

9

Вы можете достичь своей цели путем сопоставления регулярных выражений.

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") 
} 
+1

может создать способ создания этих шаблонов, возможно, так: 'def binRegex (символ: Char) = raw" "" ([^ $ symbol] +) [$ symbol] ([^ $ symbol] +) "" " .r' –

+0

Спасибо за ваш ответ, сэр! – DoSofRedRiver

2

Я так не считаю.

Вы могли бы быть в состоянии сделать это, если вы преобразовать String в List или Vector из Char и затем возвращаются результаты с mkString. Но я ничего не могу придумать.

Однако, имо, регулярное выражение будет более кратким и читабельным:

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") 
+0

Благодарим вас за ваш asnwer! – DoSofRedRiver

1

Вы также можете сделать это с помощью экстракторов:

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") 
} 

Вы также можете реализовать применять метод для каждого экстрактор, как:

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

, но это не является обязательным

+0

Похоже, ваше решение подошло мне больше всего, спасибо! – DoSofRedRiver

Смежные вопросы