【问题标题】:Parsing nested collection in scala在scala中解析嵌套集合
【发布时间】:2019-05-24 16:04:39
【问题描述】:

我有一个如下所示的集合结构。我需要根据地图中的 k,v 对来构建语句。嵌套层级事先不知道,代码需要动态解析。

结构:

case class Step(id: Option[String], stepId: Option[String], parameters: Option[Map[String, Any]])

    val sample = Step(id = Some("a1"), Some("case"), Some(
        Map(
            "CONDITIONAL" -> List(
                Map("comparison" -> List(
                    Map("comparision" -> List(
                        Map("comparision" -> List(
                            Map("comparator" -> List(
                                Map(
                                    "EVAL" -> "c11",
                                    "OPERATION" -> "equals to",
                                    "WHEN" -> List("A")),
                                Map(
                                    "eval" -> "c12",
                                    "operation" -> "in",
                                    "when" -> List("B")),
                                Map(
                                    "eval" -> "c13",
                                    "operation" -> "starts with",
                                    "when" -> List("C")
                                )),
                                "operator" -> "OR"
                            ),
                            Map("comparator" -> List(
                                Map(
                                    "EVAL" -> "c21",
                                    "OPERATION" -> "equals to",
                                    "WHEN" -> List("A")),
                                Map(
                                    "eval" -> "c22",
                                    "operation" -> "in",
                                    "when" -> List("B")
                                )),
                                "operator" -> "OR"
                            )),
                            "operator" -> "AND"
                        ),
                        Map("comparator" -> List(
                            Map(
                                "EVAL" -> "c31",
                                "OPERATION" -> "equals to",
                                "WHEN" -> List("A")),
                            Map(
                                "EVAL" -> "c32",
                                "OPERATION" -> "in",
                                "WHEN" -> List("B")),
                            Map(
                                "EVAL" -> "c33",
                                "OPERATION" -> "starts with",
                                "WHEN" -> List("C")
                            )),
                            "operator" -> "OR"
                        )),
                        "operator" -> "OR"
                    )),
                    "THEN" -> "result"
                )),
            "ELSE" -> "default"
        ))
    )

val stepsLower = sample.parameters.get.map(p => p._1.toLowerCase -> p._2)

val comparisons = stepsLower("conditional").asInstanceOf[List[Map[String, Any]]]

现在我需要通过评估结构来解析条件(比较)下的数据。

结果应该是 ((c11 OR c12 OR c13 ) AND (c21 OR c22)) OR (c31 OR c32 OR c33 OR c34)

【问题讨论】:

    标签: json scala collections


    【解决方案1】:

    这是适用于所有用例的代码 sn-p。

    case class Step(id: Option[String], stepId: Option[String], parameters: Option[Map[String, Any]])
    
    val sample1 = Step(id = Some("a1"), Some("case"), Some(Map(
        "CONDITIONAL" -> List(
          Map("comparison" -> List(
            Map("comparison" -> List(
              Map("comparison" -> List(
                Map("comparator" -> List(
                  Map(
                    "eval" -> "c11",
                    "operation" -> "equals to",
                    "when" -> List("A")),
                  Map(
                    "eval" -> "c12",
                    "operation" -> "in",
                    "when" -> List("B")),
                  Map(
                    "eval" -> "c13",
                    "operation" -> "starts with",
                    "when" -> List("C")
                  )),
                  "operator" -> "OR"
                ),
                Map("comparator" -> List(
                  Map(
                    "eval" -> "c21",
                    "operation" -> "equals to",
                    "when" -> List("A")),
                  Map(
                    "eval" -> "c22",
                    "operation" -> "in",
                    "when" -> List("B")
                  )),
                  "operator" -> "OR"
                )),
                "operator" -> "AND"
              ),
              Map("comparator" -> List(
                Map(
                  "eval" -> "c31",
                  "operation" -> "equals to",
                  "when" -> List("A")),
                Map(
                  "eval" -> "c32",
                  "operation" -> "in",
                  "when" -> List("B")),
                Map(
                  "eval" -> "c33",
                  "operation" -> "starts with",
                  "when" -> List("C")
                )),
                "operator" -> "OR"
              )),
              "operator" -> "OR"
            )),
            "then" -> "result"
          )),
        "else" -> "default"
      ))
    )
    
    
    val sample2 = Step(id = Some("a1"), Some("case"), Some(
      Map(
        "conditional" -> List(
          Map("comparison" -> List(
            Map("comparison" -> List(
              Map("comparator" -> List(
                Map(
                  "eval" -> "c11",
                  "operation" -> "equals to",
                  "when" -> List("A")),
                Map(
                  "eval" -> "c12",
                  "operation" -> "in",
                  "when" -> List("B", "b"))),
                "operator" -> "AND"),
              Map("comparator" -> List(
                Map("eval" -> "c21",
                  "operation" -> "equals to",
                  "when" -> List("A")),
                Map("eval" -> "c31",
                  "operation" -> "equals to",
                  "when" -> List("A"))),
                "operator" -> "OR")),
              "operator" -> "OR")),
            "then" -> "something"
          ),
          Map("comparison" -> List(
            Map("comparison" -> List(
              Map("comparator" -> List(
                Map(
                  "eval" -> "c111",
                  "operation" -> "equals to",
                  "when" -> List("A")),
                Map(
                  "eval" -> "c121",
                  "operation" -> "in",
                  "when" -> List("B", "b"))
              ),
                "operator" -> "AND"),
              Map("comparator" -> List(
                Map(
                  "eval" -> "c212",
                  "operation" -> "equals to",
                  "when" -> List("A")),
                Map(
                  "eval" -> "c313",
                  "operation" -> "equals to",
                  "when" -> List("A"))
              ),
                "operator" -> "OR")),
              "operator" -> "AND")),
            "then" -> "somethingelse")
        ),
        "else" -> "default"
      )
    ))
    
    
    
    def constructCase(c: List[Map[String, Any]], parentOp: Option[String] = None, parentThen: Option[String] = None): String = {
    
      val result = c.map { x =>
        val currentOp: Option[String] = x.get("operator").asInstanceOf[Option[String]]
        val currentThen: Option[String] = x.get("then").asInstanceOf[Option[String]]
    
        if (x contains "comparator") {
          "(" + x("comparator").asInstanceOf[List[Map[String, Any]]].map(x => s"${x("eval")} ${x("operation")} ${x("when").asInstanceOf[List[String]].mkString(",")}").mkString(" " + currentOp.getOrElse("") + " ") + ")"
        } else {
          val tmp = constructCase(x("comparison").asInstanceOf[List[Map[String, Any]]], currentOp, currentThen)
          if (tmp contains "WHEN") tmp else "(" + tmp + ")"
        }
      }.mkString(if (parentOp.isDefined) s" ${parentOp.get} " else "")
    
      if (parentThen.isDefined) s"WHEN $result THEN ${parentThen.get}\n" else result.trim
    }
    
    val samples = Set(sample1, sample2)
    samples.foreach { sample =>
      val stepsLower = sample.parameters.get.map(p => p._1.toLowerCase -> p._2)
    
      val comparisons = stepsLower("conditional").asInstanceOf[List[Map[String, Any]]]
    
      println("CASE \n" + constructCase(comparisons) + s"\nELSE ${stepsLower("else")}")
      println("")
    }
    

    这是结果

    CASE 
    WHEN (((c11 equals to A OR c12 in B OR c13 starts with C) AND (c21 equals to A OR c22 in B)) OR (c31 equals to A OR c32 in B OR c33 starts with C)) THEN result
    ELSE default
    
    CASE 
    WHEN ((c11 equals to A AND c12 in B,b) OR (c21 equals to A OR c31 equals to A)) THEN something
    WHEN ((c111 equals to A AND c121 in B,b) AND (c212 equals to A OR c313 equals to A)) THEN somethingelse
    ELSE default
    

    如果它不适用于您的任何用例,请告诉我。

    【讨论】:

      猜你喜欢
      • 2019-04-30
      • 1970-01-01
      • 2020-06-11
      • 1970-01-01
      • 2016-05-15
      • 2018-10-06
      • 1970-01-01
      • 2012-12-08
      • 1970-01-01
      相关资源
      最近更新 更多