1

我正在使用一个我无法更改的 api,它返回一个 2 元素映射,其中一个键始终存在,但另一个键/值对是动态的,我试图将它们解压缩到一个案例类中。下面的代码有效,但真的很难看:

case class Foo(name: String, key: String, value: String)

def fooFromMap(item: Map[String, String]): Option[Foo] = {
  var name: String = null
  var key: String = null
  var value: String = null
  item.foreach { 
    case ("name", v) => name = v
    case (k, v) => key = k; value = v
  }
  if(name != null && key != null && value != null) Some(Foo(name, key, value))
  else None
}

有没有更好的方法来做到这一点?

4

3 回答 3

3

以下是等效的,并且更惯用:

def fooFromMap(item: Map[String, String]): Option[Foo] = for {
  name   <- item get "name"
  (k, v) <- (item - "name").headOption
} yield Foo(name, k, v)

如果其中一个item get "name"(item - "name").headOption为空,则结果将为空——否则你会得到Foo你想要的。

于 2012-12-31T18:23:32.413 回答
2

如果我理解正确的话,Map总是有name键和零个或一个以上的键值对,对吧?如果是,你可以这样做:

def fooFromMap(map: Map[String, String]) =
  map.get("name").map { name =>
    val (key, value) = (map - "name").head
    Foo(name, key, value)
  }

如果您还需要检查是否Map有第二对(None如果没有则返回),那么:

def fooFromMap(map: Map[String, String]) = for {
  name <- map.get("name")
  (key, value) <- (map - "name").headOption
} yield Foo(name, key, value)

我倾向于更喜欢第二个片段,因为它更符合习惯并利用了forScala 中强大的理解。

于 2012-12-31T18:32:34.357 回答
0
def fooFromMap(map: Map[String, String]): Option[Foo] = {
  val data = m.find(_._1 != "name").getOrElse (null, null)
  Foo(m.getOrElse("name", null), data._1, data._2) match { 
    case f: Foo if (f.name != null && f.key != null && f.value != null) => Some(f)
    case _ => None
  }
}
于 2012-12-31T20:19:42.007 回答