Scala:如果在getOrElse中获得值,则执行一些操作

0s7z1bwu  于 2023-01-13  发布在  Scala
关注(0)|答案(1)|浏览(131)

如果变量是Option[Account],并且在类Account中有一个名为accountName的字符串字段。
例如:

val allAccounts: Set[Option[Account]] = Set(Some(Account1), Some(Account2), None)

如果我从getOrElse得到了一些东西,如何从Some(Account)得到accountName
我试过allAccounts.map(_.getOrElse("").accountName),但它不起作用。它不能应用于"get"部分,但"OrElse"部分
谢谢你的帮忙!
PS:想知道为什么allAccounts.map(_.map(_.accountName).getOrElse(""))可以很好地使用None值,但如果我创建另一个变量:val sampleAccount2 = NonesampleAccount2.map(_.accountName).getOrElse("")会失败吗?基本上我只是从Set(None)None

2ic8powd

2ic8powd1#

这是你最终想要实现的吗?

final case class Account(accountName: String)

val allAccounts: Set[Option[Account]] =
  Set(Some(Account("Account1")), Some(Account("Account2")), None)

def getAccountNames(maybeAccounts: Set[Option[Account]]): Set[String] =
  maybeAccounts.map(_.fold("")(_.accountName))

assert(getAccountNames(allAccounts) == Set("Account1", "Account2", ""))

您可以随意使用此代码here on Scastie
getAccountNames的另一种方法是使用mapgetOrElse的组合来代替fold,如下所示:

def getAccountNames(maybeAccounts: Set[Option[Account]]): Set[String] =
  maybeAccounts.map(_.map(_.accountName).getOrElse(""))

这可能更接近于你最初想要写的东西,在这种情况下foldmapgetOrElse基本上是等价的,根据你对当前代码库的了解,选择哪个更有意义。
此版本也可here on Scastie获得。
如果您将getOrElse应用于Option[Account]类型,则会出现问题,这意味着您试图返回Account(在Option中)或String,然后您将从该内容中询问accountName,这只在Account上有意义,而在String上没有意义。关键的区别是,在这种情况下,您首先在Option[Account]上使用map,然后在Some上使用accountName,得到Option[String],* 然后 * 你要么得到里面的内容,要么在Option为空的情况下得到默认值。
作为进一步的输入,请注意,由于您使用的是Set,如果您的输入中有多个空值,它们将有效地合并为一个,如以下示例所示:

assert(getAccountNames(Set(None, None)) == Set(""))

如果你想把空值从输出中完全删除,你可以重写上面的函数,这样它就定义为(Scastie):

def getAccountNames(maybeAccounts: Set[Option[Account]]): Set[String] =
  maybeAccounts.flatMap(_.map(_.accountName))

在这种情况下,getAccountNames可以根据for-理解来重新定义(更多关于here on the Scala documentation的主题):

def getAccountNames(maybeAccounts: Set[Option[Account]]): Set[String] =
  for {
    maybeAccount <- maybeAccounts
    account <- maybeAccount
  } yield account.accountName

最后一个例子也可以在here on Scastie中找到,您可以随意使用它。
在这两种情况下,现在有效的Assert更改为:

assert(getAccountNames(allAccounts) == Set("Account1", "Account2"))

相关问题