2012-12-31 25 views
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 
} 

有沒有更好的方式來做到這一點?

回答

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你想要的。

+0

打我吧,eheh;) –

+0

我知道它過早的優化,抱怨它,但這分配和燒傷一個新的地圖實例。它看起來好多了,但對我來說仍然不太好。 – jfager

+2

是的,這聽起來像過早優化對我,特別是因爲Scala有[特定的實現(http://www.scala-lang.org/api/current/scala/collection/immutable/Map$.html)針對小型地圖喜歡這個。 –

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理解。

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 
    } 
} 
相關問題