如何在Scala地图中优雅地处理"Key not found"?

Pra*_*ant 5 dictionary scala scala-collections

总之,如果在Map中找到了值,那么我需要一种功能性的方法来做一件事,如果没找到则做另一件事.请注意,我对返回的值不感兴趣,但已完成操作.

请继续阅读以了解详情.

我有一个服务名称(友好)的地图到URL PATH的一部分(不容易记住).这是初始化.

val serviceMap = Map("read" -> "cryptic-read-path",
  "save" -> "cryptic-save-path", "county" -> "cryptic-zip-code-to-county-service.");
Run Code Online (Sandbox Code Playgroud)

我所知道的所有替代方案都会导致带有加载then部分的if语句,但这是一个简单的404 else部分.这是我想到的一些

if (serviceMap.contains(service)) {
    //Do stuff
} else {
    //Issue a 404
}
Run Code Online (Sandbox Code Playgroud)

它等同于谓词逆转

if (!serviceMap.contains(key)) //issue a 404
//Do stuff
Run Code Online (Sandbox Code Playgroud)

上述两种方法都需要我检查然后获取.

另一个(由选项文档阻止)

  serviceMap.get(service) match {
  case _ : Option[String]=> //Do stuff
  case _  => //issue 404
}
Run Code Online (Sandbox Code Playgroud)

还有第三个

  serviceMap.get(service).forEach {//Dostuff and return, since it's just one element }
  //issue 404 if you are here.
Run Code Online (Sandbox Code Playgroud)

根据Option选项文档,我被鼓励将其Option视为一个集合,因此最后的替代方案似乎更好,但是forEach在循环之后使用看似奇怪的更改执行流程.

这是我的经验不足,但所有这些看起来都太冗长,对我不合适.你们能给我一个更好的选择或评论方法吗?在期待中感谢!

Sea*_*ira 4

有几个更清晰的选项:

  1. matchwith unapply(这避免了 的类型擦除问题_ : Option[CantTellWhatThisIsAtRuntime]):

    serviceMap.get(service) match {
      case Some(path) => // Do stuff and return
      case _ => // 404
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用 afold提取值(假设您可以正确输入 404):

    serviceMap.get(service).fold(/* 404 */) { path =>
      // Do stuff and return
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用map+getOrElse将路径转换为响应或返回/抛出 404(向 Mikesname 致敬):

    serviceMap.get(service).map { path =>
      // Do stuff and return
    } getOrElse {
      // 404
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 使用MapgetOrElse方法(假设你抛出 404):

    val path = serviceMap.getOrElse(service, throw Error404)
    // Do stuff and return
    
    Run Code Online (Sandbox Code Playgroud)