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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14569141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 04:52:49  来源:igfitidea点击:

Compare instances of Option[T] avoiding None == None

scala

提问by Soteric

Yesterday I was suddenly enlighted and understood how and why people use 'map' method with Option to compare values. Yes, I'm a bit slow, sorry :)

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

I revised these very nice links and came to the question I would like to ask.

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

http://twitter.github.com/effectivescala

http://twitter.github.com/effectivescala

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

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

In my Lift webapp I have some Option[User] and Option[Server] variables. I'm trying to find out if this User is admin of this Server by the following check

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

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

But I noticed that in case of 'user' is None and 'server' is also None this check succeeds which is not good for me (if any of them is None I'd like this check to fail). I could add user.isDefined condition but I feel there is more correct way to do it. Could you tell how to accomplish it in Scala way?

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

回答by Régis Jean-Gilles

You could do it with pattern matching (which in this case is probably the clearest way):

你可以用模式匹配来做到这一点(在这种情况下这可能是最清晰的方法):

(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
}

You could also try as a one-liner but here I don't advise it as it's pretty obfuscated:

您也可以尝试单行,但在这里我不建议这样做,因为它非常混乱:

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
}

Finally, if you only have to handle the case where the ids match (and would just do nothing if there is not), using a for comprehension is not too bad of an option (no pun intended):

最后,如果您只需要处理 ids 匹配的情况(如果不匹配就什么也不做),使用 a for comprehension 是一个不错的选择(没有双关语):

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

回答by Suma

I got used to the combination of exists/ containsfor this purpose.

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

When comparing two options of the same type:

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

o1.exists(o2.contains)

In your case this can be applied using map:

在您的情况下,可以使用map以下方法应用:

user.map(_.id).exists(server.map(_.adminId).contains)

回答by pagoda_5b

you can use a for comprehension

你可以使用 a 来理解

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

The comprehension results in a Option[Boolean]from which you getthe value or falseif there's no value (the case where any of the options is None, as you requested)

理解会导致Option[Boolean]您从中get获得价值,或者false如果没有价值(None根据您的要求,任何选项都为 的情况)

Why curried?

为什么是咖喱?

I made the method curried, so you can define you function for a specific server, and then reuse that to check many users

我将方法咖喱化,因此您可以为特定服务器定义函数,然后重用它来检查许多用户

def isMyServerAdmin = isAdmin(Some(myServer)) _

isMyServerAdmin(Some(user1)) = true
isMyServerAdmin(Some(user2)) = false
isMyServerAdmin(None) = false

回答by Xavier Guihot

We can make use of Option#zipto work with an Optionof the tuple user/server:

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

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

where the behavior of Option#zipis:

其中的行为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

and where Option#existsapplies a predicate on the optional tuple produced by zip.

和 whereOption#exists在由zip.生成的可选元组上应用谓词。