获取可选类字段的值

时间:2019-04-10 14:47:05

标签: scala

假设我有一个具有两个可选字段的Toto类:

case class Toto(a : Option[Int], b: Option[Int])

还有一个带有一个可选Toto的Titi类:

case class Titi(c : Option[Toto])

我们创建类Titi的实例:

val test = Titi(Some(Toto(Some(1),Some(2))))

现在,我想通过假设Titi或b可以等于None来访问Toto的第二个字段,但这条语句是不可能的:

test.c.getOrElse("Something").b.getOrElse(0)

我该怎么做?

5 个答案:

答案 0 :(得分:7)

您应该使用flatMap:

test.c.flatMap(_.b).getOrElse(0)

在层次结构中任何位置的情况下,将返回None 0。 如果您的对象层次结构更深入,并且属性返回Option,则可以链接flatMap

test.c
 .flatMap(_.b)
 .flatMap(_.d)
//...etc

Scala还具有用于解开深度嵌套的monadic类型的特殊语法,称为for comprehension

val result = for {
   c <- test.c
   a <- c.a
} yield a

result.getOrElse(0)

在后台,它被编译为与链接的flatMap类似的代码。

这基本上是这样的:

如果cNone,则直接进入getOrElse并返回0 如果为Some,则检查b,如果为None,则转到getOrElse,否则返回包装在Some中的值。

如果您想返回不同的东西来区分哪个Option为None,那么我只用match

test.c match {
   case Some(c) => c.getOrElse(0)
   // if you return String in one branch and integer in other then inferred type would be Any!
   case None    => "Something" 
}

答案 1 :(得分:2)

您的Val测试是错误的,应该是这个

val test = Titi(Some(Toto(Some(1),Some(2))))

另一件事,在getOrElse中,您必须放置一个有意义的类型

test.c.getOrElse(Toto(None,None))

答案 2 :(得分:2)

您可以通过模式匹配来实现

val test: Titi = Titi(Some(Toto(Some(1), None)))
val res = test.c match {
case Some(Toto(_, Some(x))) => x
case _ => 0
}

结果:

0

答案 3 :(得分:-1)

val x = test match {
    case Titi(x) => {
      x match {
        case Some(x) => {
          x.b match {
            case Some(z) => z
            case None    => 1
          }
        }
        case None => 1
      }
    }
    case _ => 1
  } //> x  : Int = 2

答案 4 :(得分:-1)

u可以使用折叠

test.c.fold(0)(_.b.fold(0)(i => i))