Разбор вложенной коллекции в scala - PullRequest
1 голос
/ 24 мая 2019

У меня есть структура коллекции, как показано ниже.Мне нужно построить оператор, основанный на 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 ИЛИ c12 ИЛИ c13) И (c21 ИЛИ c22)) ИЛИ (c31 ИЛИ c32 ИЛИ c33 ИЛИ c34)

1 Ответ

0 голосов
/ 28 мая 2019

Вот фрагмент кода, который должен работать для всех ваших вариантов использования.

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

Дайте мне знать, если этоне работает ни для одного из ваших вариантов использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...