问题
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