[英]Scala - string of algebraic operations
I have a string representing some basic algebraic operations, for example: 我有一个表示一些基本代数运算的字符串,例如:
"42 * 67 + 4"
I would like a function of type 我想要一个类型的函数
function (operation: String) : Int = {}
such that it takes a string of algebraic operations and returns the actual final value, in this case: 2818 这样它需要一串代数运算并返回实际的最终值,在这种情况下:2818
I would know how to extract the numbers from such a string but I do not have clear how to extract the mathematical operations such as '+', '-', '*', '/' and actually compute them. 我会知道如何从这样的字符串中提取数字,但是我还不清楚如何提取诸如“ +”,“-”,“ *”,“ /”之类的数学运算并实际进行计算。
It's fairly simple to implement the Shunting-yard algorithm to do this sort of calculations without any external libraries: 在没有任何外部库的情况下,实现Shunting-yard算法来进行这种计算非常简单:
def calculate(operation: String): Int = {
var results: List[Int] = Nil
var operators: List[String] = Nil
def precedence(operator: String) = operator match {
case "+" | "-" => 0
case "*" | "/" => 1
}
def execute(operator: String): Unit = {
(results, operator) match {
case (x :: y :: rest, "+") => results = (y + x) :: rest
case (x :: y :: rest, "-") => results = (y - x) :: rest
case (x :: y :: rest, "*") => results = (y * x) :: rest
case (x :: y :: rest, "/") => results = (y / x) :: rest
case (_, _) => throw new RuntimeException("Not enough arguments")
}
}
for (term <- "[1-9][0-9]*|[-+/*]".r.findAllIn(operation)) {
util.Try(term.toInt) match {
case util.Success(number) => results ::= number
case _ =>
val (operatorsToExecute, rest) =
operators.span(op => precedence(op) >= precedence(term))
operatorsToExecute foreach execute
operators = term :: rest
}
}
operators foreach execute
results match {
case res :: Nil => res
case _ => throw new RuntimeException("Too many arguments")
}
}
This uses integer division: 这使用整数除法:
scala> calculate("3 / 2")
res0: Int = 1
And has correct precedence of addition and multiplication: 并具有正确的加法和乘法优先级:
scala> calculate("2 + 2 * 2")
res1: Int = 6
Support of: 支持:
2 * (2 + 2)
, 2 * (2 + 2)
, Try[Int]
, Option[Int]
, etc. instead of the current behaviour of returning a bare Int
or throwing an error) Try[Int]
, Option[Int]
等,而不是返回裸Int
或抛出错误的当前行为) is left as an exercise to the reader. 留给读者练习。
For more complex things, of course it would be better to use scala-parser-combinators
or some third-party parsing library as proposed in other answers. 对于更复杂的事情,当然最好使用
scala-parser-combinators
或其他答案中建议的某些第三方解析库。
So, @Gábor Bakos posted his joking comment, while I was still composing and testing my joking answer, but I'll post it anyway. 因此,@GáborBakos发布了他的笑话评论,而我仍在撰写和测试我的笑话答案,但无论如何我都会将其发布。
Note: it works. 注意:有效。 Sometimes.
有时。 A bit.
一点点。 Note2: it's a joke!
注意2:这是个玩笑!
def function(operation: String) = {
val js = new javax.script.ScriptEngineManager().getEngineByName("JavaScript")
js.eval(operation) match { case i: Integer => i.asInstanceOf[Int] }
}
function("42 * 67 + 4")
// => 2818 : Int
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.