タイプに注意する必要があります。ここではm : Map[String, Any]
、acc として開始します。文字列と組み合わせてx
を呼び出すとget
、 が返されますOption[Object]
。続行するには、値があることを確認し、この値がMap
, キャストであるかどうかを確認する必要があります (型が消去されるためチェックされていないため、危険です)。
私は、あなたの構造体のタイプ Map[String, Any] があなたが持っているものをかなりうまく表現していないことに問題があると信じています。
代わりにそうするとします
sealed trait Tree
case class Node(items: Map[String, Tree]) extends Tree
case class Leaf(s: String) extends Tree
Tree の宣言を簡単にするヘルパーを追加することができます
object Tree {
implicit def fromString(s: String) = Leaf(s)
implicit def fromNamedString(nameAndValue: (String, String))
= (nameAndValue._1, Leaf(nameAndValue._2))
}
object Node {
def apply(items: (String, Tree)*) : Node = Node(Map(items: _*))
}
次に、ツリーの宣言は最初のバージョンと同じくらい簡単ですが、タイプははるかに正確です
m = Node("email" -> "a@b.com", "background" -> Node("language" -> "english"))
次に、メソッドを追加できます。たとえば、trait Tree
def get(path: String*) : Option[Tree] = {
if (path.isEmpty) Some(this)
else this match {
case Leaf(_) => None
case Node(map) => map.get(path.head).flatMap(_.get(path.tail: _*))
}
}
def getLeaf(path: String*): Option[String]
= get(path: _*).collect{case Leaf(s) =>s}
または、折り畳みでそれを行う場合
def get(path: String*) = path.foldLeft[Option[Tree]](Some(this)) {
case (Some(Node(map)), p) => map.get(p)
case _ => None
}