将混合语义映射解压缩到案例类中

时间:2012-12-31 18:03:12

标签: scala

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

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
}

有更好的方法吗?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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)

我倾向于选择第二个片段,因为它更加惯用,并且在Scala中使用了强大的for推理。

答案 2 :(得分: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
  }
}