比较Option [T]的实例,避免None == None

时间:2013-01-28 18:58:22

标签: scala

昨天我突然明白了,并了解人们如何以及为什么人们使用'map'方法和Option来比较值。是的,我有点慢,抱歉:)

我修改了这些非常好的链接,并提出了我想问的问题。

http://twitter.github.com/effectivescala

http://blog.tmorris.net/posts/scalaoption-cheat-sheet

在我的Lift webapp中,我有一些Option [User]和Option [Server]变量。我试图通过以下检查来确定此用户是否是此服务器的管理员

if(user.map(_.id) == server.map(_.adminId))

但我注意到,如果'user'为None且'server'也是None,则此检查成功,这对我不利(如果其中任何一个为None,我希望此检查失败)。我可以添加user.isDefined条件,但我觉得有更多正确的方法来做到这一点。你能告诉我们如何用Scala方式完成它吗?

4 个答案:

答案 0 :(得分:21)

您可以使用模式匹配(在这种情况下可能是最清晰的方式):

(user, server) match {
  case (Some(user), Some(server)) if user.id == server.adminId =>
    // both ids are matching, handle this case here
  case _ =>
    // no match, handle this case here
}

你也可以尝试作为一个单行,但在这里我不建议它,因为它很混淆:

if ( user.flatMap{ user => server.map(_.adminId == user.id) }.getOrElse( false ) ) {
  // both ids are matching, handle this case here
}
else {
  // no match, handle this case here
}

最后,如果你只需要处理id匹配的情况(如果不匹配则不会做任何事情),使用for comprehension对于一个选项来说并不是太糟糕(没有双关语):

for ( user <- user; server <- server if user.id == server.adminId ) {
  // both ids are matching, handle this case here
}

答案 1 :(得分:9)

为此,我习惯了exists / contains的组合。

比较两种相同类型的选项时:

o1.exists(o2.contains)

在您的情况下,可以使用map

来应用此功能
user.map(_.id).exists(server.map(_.adminId).contains)

答案 2 :(得分:2)

你可以使用for comprehension

def isAdmin(server: Option[Server])(user: Option[User]): Boolean = (for {
    s <- server
    u <- user
  } yield (u.id == s.adminId)
).getOrElse(false)

理解会产生Option[Boolean]getfalseNone如果没有值(任何选项为def isMyServerAdmin = isAdmin(Some(myServer)) _ isMyServerAdmin(Some(user1)) = true isMyServerAdmin(Some(user2)) = false isMyServerAdmin(None) = false 的情况,就像你一样)请求)

为什么选择咖喱?

我将该方法设为curry,因此您可以为特定服务器定义函数,然后重复使用该函数来检查许多用户

{{1}}

答案 3 :(得分:0)

我们可以使用Option#zipOption的元组用户/服务器一起使用:

user zip server exists { case (user, server) => user.id == server.adminId }

Option#zip的行为是:

Some(User(id = "hello")) zip Some(Server(adminId = "world"))
// Some((User("hello"), Server("world")))
Some(User(id = "hello")) zip None        // None
None zip Some(Server(adminId = "world")) // None
None zip None                            // None

,其中Option#existszip产生的可选元组上应用谓词。