像"(school A and school B) or (school C or school D)"
这样的字符串。
所以字符串如下:
val queryString = "(school A and school B) or (school C or school D)"
预期产出
val firstList = List ( "school A", "school B", "and" )
val secondList = List ( "school C", "school D" , "or")
val operatorList = List("or")
和queryString
也应该是and
条件:
val queryString = "(school A and school B) and (school C or school D)"
预期产出
val firstList = List ( "school A", "school B", "and" )
val secondList = List ( "school C", "school D" , "or")
val operatorList = List("and")
也有一段时间queryString
应该只有这样一个标准:
val queryString = "(school A and school B)"
预期产出
val firstList = List ( "school A", "school B", "and" )
val secondList = empty list
val operatorList = empty list
firstList
包含字符串第一个开括号和右括号数据(school A and school B)
,firstList
与List ( "school A", "school B", "and" )
secondList
相同。
我用最后一个字符串做如下:
val queryString = "(school A and school B)"
此替换为( and ) to ""
并由and
queryString.replaceAll("\\(|\\)","").split("and")
这个返回Array("school A ", " school B")
但是在上面的代码中我手动分割and
这个工作在(school A and school B)
只有这个字符串如果字符串很大那么这个逻辑就失败了。
答案 0 :(得分:4)
我建议使用解析器组合器来完成这项任务。 毫无疑问,你需要一些时间来弄清楚它是如何工作的。 但这里的基本实现适用于一半的样本。
您可以改进它以适用于所有情况。
class SParser extends RegexParsers {
def word = "\\w+".r
def or = "or"
def oper = "and" | "or"
def oneQ = "(" ~ word ~ oper ~ word ~ ")" ^^ {
case _ ~ s1 ~ op ~ s2 ~ _ => List(s1, s2, op)
}
def q1 = oneQ ~ oper ~ oneQ ^^ {
case s1 ~ op ~ s2 =>
println("firstList : " + s1)
println("secondList: " + s2)
println("operatorList: " + op)
(s1, s2, op)
}
def parse(s: String) = {
println(s"Start parse: $s")
val res = parseAll(q1, s)
println(res)
res
}
}
用法:
val s = new SParser()
s.parse("(SchoolA and SchoolB) or (SchoolC and SchoolD)")
s.parse("(SchoolA and SchoolB) and (SchoolC and SchoolD)")
// s.parse("(SchoolA and SchoolB)") // will not work for it. need implement...
输出:
Start parse: (SchoolA and SchoolB) or (SchoolC and SchoolD)
firstList : List(SchoolA, SchoolB, and)
secondList: List(SchoolC, SchoolD, and)
operatorList: or
Start parse: (SchoolA and SchoolB) and (SchoolC and SchoolD)
firstList : List(SchoolA, SchoolB, and)
secondList: List(SchoolC, SchoolD, and)
operatorList: and
<强>更新强>
import scala.util.parsing.combinator.RegexParsers
class SParser extends RegexParsers {
def space = "\\s".r
def schholName = "\\w+\\s\\w".r // regex for <school X>
def and = "and"
def or = "or"
def eof = "$".r
def oneQ(oper: String) = "(" ~ repsep(schholName, oper) ~ ")" ^^ {
case _ ~ s1 ~ _ => s1 ++ (1 until s1.size).map( _ => oper) // add operators at the end
}
def allOneQ = oneQ(and) | oneQ(or)
def q1(oper: String) = repsep(allOneQ, oper) ^^ {
case s1 =>
val res = s1 ++ (1 until s1.size).map(_ => oper)
println("Lists : " + res)
res
}
def fullQ = q1(and) ~ eof | q1(or) ~ eof
def parse(s: String) = {
println(s"Start parse: $s")
val res = parseAll(fullQ, s)
println(res)
res
}
}
用法
val s = new SParser()
s.parse("(school A or school B)")
s.parse("(school A and school B and school E)")
s.parse("(school A or school B or school E) or (school C and school D)")
结果
Start parse: (school A or school B)
Lists : List(List(school A, school B, or))
Start parse: (school A and school B and school E)
Lists : List(List(school A, school B, school E, and, and))
Start parse: (school A or school B or school E) or (school C and school D)
Lists : List(List(school A, school B, school E, or, or))
Lists : List(List(school A, school B, school E, or, or), List(school C, school D, and), or)
答案 1 :(得分:1)
我想用parboiled2
来推动V.先生的回答虽然它超出了问题范围,但让我介绍一些检查复杂条件的适当结构
trait Query {
def check(valid: String => Boolean): Boolean
}
case class School(name: String) extends Query {
def check(valid: (String) => Boolean) = valid(name)
}
case class And(queries: Seq[Query]) extends Query {
def check(valid: (String) => Boolean) = queries.forall(_.check(valid))
}
case class Or(queries: Seq[Query]) extends Query {
def check(valid: (String) => Boolean) = queries.exists(_.check(valid))
}
case object False extends Query {
def check(valid: (String) => Boolean) = false
}
case object True extends Query {
def check(valid: (String) => Boolean) = true
}
此处School(A)
将解析等效于school A
And
,Or
是and
\ {{}}条件的合并者
or
和True
是实用的常数条件。
每个False
都可以运行一些查询,其中包含叶Query
s
让我们通过parboiled2创建解析器毛发这样的结构,这比V先生建议的标准scala解析器组合更快。
School
现在您可以尝试解析并运行查询
object Query {
class QueryParser(val input: ParserInput) extends Parser {
def element: Rule1[Query] = rule {school | group}
def group: Rule1[Or] = rule {"(" ~ WS ~ disjunction ~ WS ~ ")"}
def conjunction: Rule1[And] = rule {element.+(and) ~> And.apply _}
def disjunction: Rule1[Or] = rule {conjunction.+(or) ~> Or.apply _}
def school = rule {"school " ~ WS ~ capture(schoolName) ~> School.apply _}
def schoolName = rule {oneOrMore(CharPredicate.Alpha)}
def or = rule {WS ~ "or" ~ WS}
def and = rule {WS ~ "and" ~ WS}
def WS = rule {zeroOrMore(anyOf(" \n\r\t\f"))}
}
def parse(str: String) = new QueryParser(str).disjunction.run().toOption
}