Scala Recursive Reduction

纵然是瞬间 提交于 2019-12-25 07:16:45

问题


I have a case class that is recursive and looks like this:

case class Config(name: String, isEnabled: Boolean, elems: Map[String, MyCase])

case class MyCase(
  id: String,
  isActive: Boolean,
  elems: Option[Map[String, MyCase]])

Where the Config contains the id of the MyCase entries contained as a Map. I have to iterate over this structure and come up with a Map that contains the parent child relations. Say for example., if I have the Config class represented as below (for simplicity, I have just given the id's):

Config(Map("5" -> myCase1, "6" -> myCase2))

5 - Config
 1
  1
  2 
 2
6
 1

where id's 5 and 6 are top level entries which in turn has a recursive structure. I have to now come up with a Map that contains the parent child relationship for the id's. So for the case above, I will expect a Map that looks like:

Map(
 "5" -> Seq("5.1"),
 "5.1" -> Seq("5.1.1", "5.1.2"),
 "5.1.1" -> Seq.empty[String],
 "5.1.2" -> Seq.empty[String],
 "6" -> Seq("6.1"),
 "6.1" -> Seq.empty[String]
)

Notice how I append the parent id to the child.

Given a Seq of such Configs,

val configs = Seq(Config1, Config2)

this is what I have come up with:

def relationsFor(config: Config): Map[String, Seq[String]] = {

    def prepareChildren(parentId: String, acc: Map[String, Seq[String]], subElems: Map[String, MyCase]): Map[String, Seq[String]] = {
      subElems.collect {
        case (id, elem) if elem.isActive =>
          val newAcc = acc ++ Map(parentId -> subElems.keys.map(subElemId => s"$parentId.$subElemId").toSeq)
          if (elem.elems.isDefined) {
            val newParentId = s"$parentId.$id"
            val newAcc1 = newAcc ++ Map(s"$parentId.$id" -> elem.elems.get.keys.map(subElemId => s"$newParentId.$subElemId").toSeq)
            prepareChildren(s"$parentId.$id", newAcc1, elem.elems.get)
          } else {
            acc ++ Map(s"$parentId.$id" -> Seq.empty[String])
          }
      }
    }.flatten.toMap

    configs.collect {
      case config if config.isEnabled =>
        config.elems.collect {
          case (parentId, elemCase) if elemCase.elems.isDefined =>
            prepareChildren(parentId, Map.empty[String, Seq[String]], elemCase.elems.get)
          case (parentId, _) =>
            Map(parentId -> Seq.empty[String])
        }
    }.flatten.flatten.toMap
  }

Could this be simplified ? I have already tested this and it works as expected, but I find it a little bit hard to understand. Can this be made much more elegant? I mean can the relationsFor method be made more elegant ?

来源:https://stackoverflow.com/questions/38143191/scala-recursive-reduction

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!