2016-11-01 86 views
0

爲什麼我的val pairOpt a Option[Option[String,String]]試圖返回一個地圖,但目前正在返回一個Iterable

我想擁有它,所以它返回Option[(String, String)]

def blah(..): Map[String, String] = { 

    val map: Map[String, String] = // 
    val boolTry = Try(map.getOrElse("key1", "").trim.toBoolean) 
    val intTry = Try(map.getOrElse("key2, "").trim.toInt) 

    val pairOpt: Option[Option[(String, String)]] = for { 
    b <- boolTry.toOption 
    i <- intTry.toOption 
    } yield { 
    val res: Option[String] = (b, i) match { 
     case (true, 1) => Some("a") 
     case (false, 2 | 3 | 7) => Some("b") 
     case (true, 5 | 9 | 11) => Some("c") 
     case _ => None 
    } 
    res.map("foo" -> _) 
    } 

    map ++ pairOpt // map + ("foo" -> "c") 

} 

返回值也currenly Iterable[Product with Serializable]時,我希望它是Map[String,String]

我在這裏錯過了什麼?

+0

你它返回地圖[字符串,字符串]或Option [(字符串,字符串)?我相信迭代是返回的,因爲它只是可能的類型,它滿足向選項[Option [String,String]]添加Map [String,String]。 – pedrofurla

+0

@pedrofurla我希望for-comp返回Option [String,String]和返回Map [String,String]的方法, –

回答

3

你會得到一個Option[Option[..]]因爲你有「可選性」在這裏,你必須的兩個「層」拉平

  • 如果boolTryintTry一個是Failure - 你會得到None
  • 否則,如果他們都Success但它們的值不匹配任何東西,你會得到Some(None)
  • 否則,你會得到Some(Some(..))

更一般地,給定一個opt: Option[V],類型如下形式的表達:

for { 
    x <- opt 
    .. 
} yield { 
    val y: T 
    y 
} 

Option[T] - 成opt.flatMap(...).map(...)其保留了「外部」的結構,因爲它轉換(無論是一個OptionListSeq等)。在你的情況下,T = Option[(String, String)],所以結果的類型Option[Option[(String, String)]]。爲了解決這個問題 - 您可以使用flatten

val pairOpt: Option[(String, String)] = (for { 
    b <- boolTry.toOption 
    i <- intTry.toOption 
    } yield { 
    // same as you did... 
    }).flatten 

這也將修復與方法的返回類型的問題(現在map ++ pairOpt將有類型Map[String, String]如預期)。

爲了避免這種呼叫flatten - 也許是一個更清潔的方式來達到同樣的將是:

val maybeTuple: Option[(Boolean, Int)] = boolTry.flatMap(b => intTry.map((b, _))).toOption 

val pairOpt: Option[(String, String)] = maybeTuple.flatMap { 
    case (true, 1) => Some("a") 
    case (false, 2 | 3 | 7) => Some("b") 
    case (true, 5 | 9 | 11) => Some("c") 
    case _ => None 
}.map("foo" -> _) 
相關問題