jef*_*eon 4 reduce scala map fold
我有一个嵌套的地图m,如:
m = Map("email" -> "a@b.com", "background" -> Map("language" -> "english"))
我有一个阵列 arr = Array("background","language")
如何foldLeft/reduce数组并从地图中找到字符串"english".我试过这个:
arr.foldLeft(m) { (acc,x) => acc.get(x) }
但我得到这个错误:
<console>:10: error: type mismatch;
found : Option[java.lang.Object]
required: scala.collection.immutable.Map[java.lang.String,java.lang.Object]
arr.foldLeft(m) { (acc,x) => acc.get(x) }
Run Code Online (Sandbox Code Playgroud)
Did*_*ont 12
你应该注意类型.在这里,你从m : Map[String, Any]acc 开始.你结合一个字符串x和调用get,返回一个Option[Object].要继续,您必须检查是否有值,检查此值是否为a Map,强制转换(由于类型擦除而未选中,因此很危险).
我认为错误在于你的结构类型Map [String,Any]代表你所拥有的东西相当糟糕.
假设你做了
sealed trait Tree
case class Node(items: Map[String, Tree]) extends Tree
case class Leaf(s: String) extends Tree
Run Code Online (Sandbox Code Playgroud)
您可以添加一些帮助程序来轻松声明树
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: _*))
}
Run Code Online (Sandbox Code Playgroud)
然后声明树就像第一个版本一样简单,但类型更精确
m = Node("email" -> "a@b.com", "background" -> Node("language" -> "english"))
Run Code Online (Sandbox Code Playgroud)
然后,您可以添加方法,例如 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}
Run Code Online (Sandbox Code Playgroud)
或者如果你愿意用折叠来做
def get(path: String*) = path.foldLeft[Option[Tree]](Some(this)) {
case (Some(Node(map)), p) => map.get(p)
case _ => None
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4680 次 |
| 最近记录: |