我有一个嵌套的地图m,如下所示:
m = Map("email" -> "a@b.com", "background" -> Map("language" -> "english"))
我有一个数组arr = Array("background","language")
如何foldLeft/reduce数组并从map中找到字符串"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) }发布于 2011-10-11 16:48:34
你应该注意类型。在这里,您首先使用m : Map[String, Any]作为您的访问权限。您将与一个字符串x组合,并调用返回Option[Object]的get。要继续,你必须检查是否有一个值,检查这个值是否是一个Map,cast (由于类型擦除而未选中,因此是危险的)。
我认为错误在于你的结构的类型,MapString,Any,Any代表了你拥有的相当糟糕的东西。
假设你这样做了
sealed trait Tree
case class Node(items: Map[String, Tree]) extends Tree
case class Leaf(s: String) extends 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
}发布于 2011-10-11 16:48:53
实际上并不支持将折叠作为嵌套地图上的抽象。此外,您正在以一种阻止类型系统为您提供太多帮助的方式处理此问题。但是,如果您坚持,那么您需要一个递归函数:
def lookup(m: Map[String,Object], a: Array[String]): Option[String] = {
if (a.length == 0) None
else m.get(a(0)).flatMap(_ match {
case mm: Map[_,_] => lookup(mm.asInstanceOf[Map[String,Object]],a.tail)
case s: String if (a.length==1) => Some(s)
case _ => None
})
}https://stackoverflow.com/questions/7723024
复制相似问题