如何在Scala中反规范化嵌套映射,反规范化字符串只包含值?

如何在Scala中反规范化嵌套映射,反规范化字符串只包含值?,scala,dictionary,functional-programming,denormalization,Scala,Dictionary,Functional Programming,Denormalization,一般来说,我不熟悉Scala和FP,想知道如何在Scala中对嵌套集合进行非规范化。例如,如果我们有考试试卷的数据: Map("subject" -> "science", "questionCount" -> 10, "questions" -> Map("1" -> Map("ques" -> "What is sun?", "answers" -> Map("1" -> "Star", "2" -> "Giant bu

一般来说,我不熟悉Scala和FP,想知道如何在Scala中对嵌套集合进行非规范化。例如,如果我们有考试试卷的数据:

Map("subject" -> "science", "questionCount" -> 10, "questions" ->
  Map("1" ->
    Map("ques" -> "What is sun?", "answers" ->
      Map("1" -> "Star", "2" -> "Giant bulb", "3" -> "planet")
    ), "2" ->
    Map("ques" -> "What is moon?", "answers" ->
      Map("1" -> "Giant rock", "2" -> "White lamp", "3" -> "Planet")
    )
  )
)
当反规范化为字符串时,仅使用值,它可以写为:

science,2,1,What is sun?,Star
science,2,1,What is sun?,Giant bulb
science,2,1,What is sun?,planet
science,2,2,What is moon?,Giant rock
science,2,2,What is moon?,White lamp
science,2,2,What is moon?,Plane
我知道我可以使用
map
处理集合中的每个项目,它返回的项目数完全相同。此外,虽然可以使用
flatMap
将每个项目处理为多个项目,并返回比集合中更多的项目,但我无法理解如何使用它进行非规范化

还有,是否可以像这样进行部分非规范化

science,2,1,What is sun?,[Star,Giant bulb,planet]
science,2,2,What is moon?,[Giant rock,White lamp,Planet]

使用
Map[String,Any]
类型的嵌套映射将永远不会有什么好处,因为您必须始终强制转换嵌套值

如果每个答案都需要
字符串
,可以
flatMap
查看问题,然后
map
查看答案

def normalize(map: Map[String, Any]): Seq[String] = {
  val subject = map("subject")
  val questions = map("questions").asInstanceOf[Map[String, Any]]
  val size = questions.size // or map("questionCount") ?
  val lines = questions.flatMap { case (id, q) => 
    val question = q.asInstanceOf[Map[String, Any]]
    val answers = question("answers").asInstanceOf[Map[String, Any]]
    answers.values.map(answer => 
      List(subject, size, id, question("ques"), answer) mkString ","
    )
  }
  lines.toSeq
}
如果您希望每个问题都有一个
字符串
(部分非规范化),您可以将问题映射到

def seminormalize(map: Map[String, Any]): Seq[String] = {
  val subject = map("subject")
  val questions = map("questions").asInstanceOf[Map[String, Any]]
  val size = questions.size // or map("questionCount") ?
  val lines = questions.map { case (id, q) => 
    val question = q.asInstanceOf[Map[String, Any]]
    val answers = question("answers").asInstanceOf[Map[String, Any]]
    List(subject, size, id, question("ques"), answers.values.mkString("[", "," , "]")) mkString ","
  }
  lines.toSeq
}
我们可以使用
规范化
半规范化
作为:

scala> normalize(map).foreach(println)
science,2,1,What is sun?,Star
science,2,1,What is sun?,Giant bulb
science,2,1,What is sun?,planet
science,2,2,What is moon?,Giant rock
science,2,2,What is moon?,White lamp
science,2,2,What is moon?,Planet

scala> seminormalize(map).foreach(println)
science,2,1,What is sun?,[Star,Giant bulb,planet]
science,2,2,What is moon?,[Giant rock,White lamp,Planet]

在问题中,地图条目使用不同:

  • 这里它们必须是序列:
    Map(“主题”->“科学”,“问题计数”->10,
  • 在这里,他们必须创建不同的行:
    Map(“1”->“星形”、“2”->“巨型灯泡”…
  • 首先,我建议引入顺序和选择的概念

    然后,我将按如下方式实现非规范化:

    object Runner3 extends App {
      case class Sequence(items: List[(String, Any)])
      case class Choices(items: List[Any])
    
      val source = Sequence(List(
        "subject" -> "science",
        "questionCount" -> 2,
        "questions" -> Choices(List(
          Sequence(List(
            "ques" -> "What is sun?",
            "answers" -> Choices(List("Star", "Giant bulb", "planet")))),
          Sequence(List(
            "ques" -> "What is moon?",
            "answers" -> Choices(List("Giant rock", "White lamp", "Planet"))))))))
    
      def denormalize(seq: Sequence): List[List[String]] =
        seq.items.map {
          case (_, choices: Choices) => denormalize(choices)
          case (_, otherValue) => List(List(otherValue.toString))
        }.reduceLeft(
            (list1: List[List[String]], list2: List[List[String]]) =>
              for(item1 <- list1; item2 <- list2) yield item1 ::: item2
          )
      def denormalize(choices: Choices): List[List[String]] =
        choices.items.flatMap {
          case seq: Sequence => denormalize(seq)
          case otherValue => List(List(otherValue.toString))
        }
    
      denormalize(source).foreach(line => println(line.mkString(",")))
    }
    
    对象Runner3扩展应用程序{
    案例类别顺序(项目:列表[(字符串,任意)])
    案例类别选择(项目:列表[任何])
    val源=序列(列表(
    “主题”->“科学”,
    “问题计数”->2,
    “问题”->选项(列表)(
    顺序(列表)(
    “问题”->“太阳是什么?”,
    “答案”->选项(列表(“恒星”、“巨型灯泡”、“行星”)),
    顺序(列表)(
    “月亮是什么?”,
    “答案”->选择(列表(“巨石”、“白灯”、“行星”()()())("巨石”、“白灯”、“行星”)()(
    def非规范化(seq:Sequence):列表[列表[字符串]]=
    seq.items.map{
    案例(u,选项:选项)=>非规范化(选项)
    大小写(u,otherValue)=>List(List(otherValue.toString))
    }约瑟夫特先生(
    (列表1:List[List[String]],列表2:List[List[String]])=>
    for(item1列表(列表(otherValue.toString))
    }
    反规范化(source.foreach)(line=>println(line.mkString(“,”))
    }