使用以下代码,我可以将地图中的键值与值进行比较。 例如,“column1> 2”将比较map(“column1”)> 2,并且结果为true或false,基于地图。但是如何处理这样的地图列表呢?我在数据库中有一个表,所以我将得到一个行列表,每行可以表示为一个映射,然后我需要处理每一行,并打印该行是否匹配条件。我知道可以很容易地在sql中完成,但我想知道如何在scala中完成。
package test
import scala.util.parsing.combinator.syntactical._
object BookParse extends StandardTokenParsers {
val lookup=Map[String,Double]("column1"->1,"column2"->2)
lexical.delimiters ++= List(">","<",">=","!=","<>","<=","=")
def value[double] = numericLit ^^ { s => s.toDouble }
def columnValue[double]=ident ^^ {s=>lookup(s)}
def condition=(columnValue|value)~(">"|"<"|"<="|">="|"<>"|"!="|"=")~(columnValue|value) ^^ {
case left ~x ~ right=>{
x match {
case ">" =>if (left > right) println("true") else println("false")
case "<" =>if (left < right) println("true") else println("false")
case "<>"=>if (left != right) println("true") else println("false")
case "!="=>if (left != right) println("true") else println("false")
case ">="=>if (left >= right) println("true") else println("false")
case "<="=>if (left <= right) println("true") else println("false")
case "="=> if (left == right) println("true") else println("false")
}
}
}
def parse(s: String) = {
val tokens = new lexical.Scanner(s)
phrase(condition)(tokens)
}
def test(extrString: String) = {
parse(extrString) match {
case Success(_,_) => println("done")
case Failure(msg, _) => println("Failure: " + msg)
case Error(msg, _) => println("Error: " + msg)
}
}
def main(args: Array[String]) {
test("column1 > 2")
}
}
答案 0 :(得分:1)
一个稍微好一点的方法就是让解析器返回&#34;表达式&#34;可以在地图的上下文中评估(而不是依赖于解析器内的副作用)。
import scala.util.parsing.combinator.syntactical._
object BookParse extends StandardTokenParsers {
lexical.delimiters ++= List(">", "<", ">=", "!=", "<>", "<=", "=")
val value: Parser[Map[String, Double] => Double] =
numericLit ^^ (v => _ => v.toDouble)
val columnValue: Parser[Map[String, Double] => Double] =
ident ^^ (name => env => env(name))
val condition: Parser[Map[String, Double] => Boolean] =
(columnValue | value) ~
(">" | "<" | "<=" | ">=" | "<>" | "!=" | "=") ~
(columnValue | value) ^^ {
case left ~ ">" ~ right => env => left(env) > right(env)
case left ~ "<" ~ right => env => left(env) < right(env)
case left ~ "<>" ~ right => env => left(env) != right(env)
case left ~ "!=" ~ right => env => left(env) != right(env)
case left ~ ">=" ~ right => env => left(env) >= right(env)
case left ~ "<=" ~ right => env => left(env) <= right(env)
case left ~ "=" ~ right => env => left(env) == right(env)
}
def parse(s: String) = {
val tokens = new lexical.Scanner(s)
phrase(condition)(tokens)
}
}
现在,如果您有一些示例数据:
val rows: List[Map[String, Double]] = List(
Map("column1" -> 1, "column2" -> 2),
Map("column1" -> 3, "column2" -> 3)
)
您可以写下以下内容:
scala> val myCond = BookParse.parse("column1 > 2").get
myCond: Map[String,Double] => Boolean = <function1>
scala> rows.filter(myCond)
res0: List[Map[String,Double]] = List(Map(column1 -> 3.0))
(请注意,有几种方法可以改善错误处理。)