总之,如果在Map中找到了值,那么我需要一种功能性的方法来做一件事,而如果找不到,则需要做另一件事。 请注意,我对返回的值不感兴趣,但已完成操作。
继续阅读详情。
我有一个服务名称(友好)地图到URL PATH的一部分(不容易记住)。 这是初始化。
val serviceMap = Map("read" -> "cryptic-read-path",
"save" -> "cryptic-save-path", "county" -> "cryptic-zip-code-to-county-service.");
我所知道的所有替代方案都会导致if语句带有加载的then
部分,但只有一个简单的404
else
部分。
以下是我想到的一些
if (serviceMap.contains(service)) {
//Do stuff
} else {
//Issue a 404
}
它等同于谓词反转
if (!serviceMap.contains(key)) //issue a 404
//Do stuff
上述两种方法都要求我检查然后获取。
另一个(由Option documentation劝阻)
serviceMap.get(service) match {
case _ : Option[String]=> //Do stuff
case _ => //issue 404
}
还有第三个
serviceMap.get(service).forEach {//Dostuff and return, since it's just one element }
//issue 404 if you are here.
根据Option documentation,我被鼓励将Option
视为一个集合,所以最后一个选择似乎更好,但使用forEach
似乎很奇怪,在循环后改变执行流程。
这是我的经验不足,但所有这些看起来都太冗长,对我不合适。你们能给我一个更好的选择或评论方法吗? 在期待中感谢!
答案 0 :(得分:4)
我认为习惯的方式是使用map
和getOrElse
:
val result = serviceMap.get(service).map { url =>
// do something with url
} getOrElse {
// not found
}
一般情况下,不要将Option
视为循环的单元素集合(这不是功能方法),而是转换进入别的东西。
答案 1 :(得分:3)
更清晰的几个选项:
match
unapply
(避免了_ : Option[CantTellWhatThisIsAtRuntime]
的类型删除问题):
serviceMap.get(service) match {
case Some(path) => // Do stuff and return
case _ => // 404
}
使用fold
提取值(假设您可以正确输入404):
serviceMap.get(service).fold(/* 404 */) { path =>
// Do stuff and return
}
使用map
+ getOrElse
将路径转换为响应或返回/抛出404(hat tip to Mikesname):
serviceMap.get(service).map { path =>
// Do stuff and return
} getOrElse {
// 404
}
使用Map
' getOrElse
方法(假设你扔掉了404):
val path = serviceMap.getOrElse(service, throw Error404)
// Do stuff and return
答案 2 :(得分:3)
就个人而言,我会使用模式匹配来做到这一点。它使它非常易读。
serviceMap.get(service) match {
case Some(s) => println("Here's my string from the map! " + s)
case _ => //issue 404
}
此外,可以轻松修改代码。例如,如果在将来某个时候你需要做一些事情,如果专门针对映射到“神秘读取路径”的值,你可以这样做:
serviceMap.get(service) match {
case Some("cryptic-read-path") => //do stuff that is specific for cryptic read path
case Some(s) => println("Here's my string from the map! " + s)
case _ => //issue 404
}
对于第三种选择,您建议在foreach内部返回。这将导致非本地回报,这是无效的。 详细了解here
编辑: 如果您不需要get调用的结果,也可以执行此操作:
serviceMap.get(service) match {
case Some(_) => //do stuff
case _ => //issue 404
}
答案 3 :(得分:1)
您的目标是根据现有或不存在的值执行不同的操作。虽然模式匹配是一种将Option
转换为值的惯用方法,但我认为它完全适合作为分支机制在多个操作之间进行选择。出于这个原因,我建议使用您提议的match
替代方案。
但是,如果您不同意这是合适的,请考虑将您的问题视为将Option
转换为操作的问题:
val response = serviceMap.get(service).map { value =>
// do stuff to convert into a 200 response
}.getOrElse {
// create 404 response
}
map
将任意Some[String]
转换为Some[Response]
,同时保持None
。现在您已拥有Option[Response]
,可以使用getOrElse
替换您的404回复,以获得None
的可能性。
答案 4 :(得分:1)
将Map
提升为仅为映射键定义的部分函数,例如,对于给定的映射
val a = Map( 1->2, 3->4)
我们可以使用
解除a
a.lift
Int => Option[Int] = <function1>
等等
a.lift(1)
Option[Int] = Some(2)
a.lift(0)
Option[Int] = None
然后考虑一下如此理解,例如
val ok = for { v <- a.lift(1); res <- Some(awesome_stuff(v)) }
yield res
ok getOrElse report404
如果v
或res
未成功(即None
),则ok
为None
。