我有一个函数,作为参数获取一个对象,如果它是正确的类型,我需要访问Option[List[Int]]
中的最后一个元素。我有一个有效的解决方案,但它看起来很笨拙。如果obj.listOfThings
中没有任何项目,我需要i
的值为0.有没有更好的方法来实现这一目标?
val i = foo match {
case obj: Bar =>
obj.listOfInts match {
case Some(ints) =>
ints.last
case _ =>
0
}
case _ =>
0
}
从技术上讲,它可以返回Option[Int]
。我对Scala还很陌生,并希望学习更好的方法解决这类问题。
答案 0 :(得分:4)
在你的情况下,似乎Ende Neu建议的是正确的方法:
val i = foo match {
case obj: Bar =>
obj.listOfInts.map(_.last /* This throws an exception when the list is empty*/).getOrElse(0)
case _ =>
0
}
但是如果你调查一下,你会发现你的代码中有一个错误,在那个obj.listOfInts is Some(Nil)
的情况下,因为在这种情况下你得到一个NoSuchElementException试图在空列表上调用last 。
请使用foo = Bar(Some(Nil))
试用此代码并亲眼看看。
当您使用Option [List]时,请仔细考虑这是否是您想要的。 通常在考虑之后你会废弃Option而只留下List,因为Option没有任何意义。 我与许多错误使用Option [List]的开发人员合作,因为他们不理解Nil和None之间的相似性,通常'None'案例最终扮演的角色与Some(Nil)相同
所以你最终不得不这样做:
optionalList match {
case None => // do something
case Some(list) =>
list match {
case Nil => // do the same thing
case head::tail => // do other stuff
}
}
如您所见,无案例和Some(Nil)案例基本相同。
要修复您的错误,您应该这样做:
case class Bar(listOfInts: Option[List[Int]])
val i = foo match {
case Bar(Some(list)) if list != Nil => list.last
case _ => 0
}
答案 1 :(得分:2)
您可能希望在此使用flatMap
和lastOption
:
obj.listOfInts.flatMap(_.lastOption)
如果listOfInts
为None
,或者为Some(Nil)
,则会返回None
。否则它将返回最后一个元素。如果您想返回0
而不是None
,请使用getOrElse
:
obj.listOfInts.flatMap(_.lastOption).getOrElse(0)
如果你想使用匹配,你可以这样做:
obj.listOfInts match {
case Some(list@(hd::tl)) => list.last
case _ => 0
}
此处,hd::tl
保证list
不为空。另一种选择是使用条件匹配:
obj.listOfInts match {
case Some(list) if list.nonEmpty => list.last
case _ => 0
}
或者首先匹配None
和Some(Nil)
个案例:
obj.listOfInts match {
case None | Some(Nil) => 0
case Some(list) => list.last
}
答案 2 :(得分:1)
正如评论中所建议的那样,我认为最好的方法是:
val i = foo match {
case obj: Bar => obj.listOfInts.map(_.last).getOrElse(0)
case _ => 0
}
答案 3 :(得分:0)
更简洁的方式,包括instanceof:
scala> case class B(is: Option[List[Int]])
defined class B
scala> def f(x: Any) = Option(x) collect { case b: B => b.is flatMap (_.lastOption) } flatten
f: (x: Any)Option[Int]
scala> f(B(Option(5 to 7 toList)))
res0: Option[Int] = Some(7)
或
scala> import PartialFunction.{ condOpt => when }
import PartialFunction.{condOpt=>when}
scala> def g(x: Any) = when(x) { case b: B => b.is flatMap (_.lastOption) } flatten
g: (x: Any)Option[Int]
scala> g(B(Option(5 to 7 toList)))
res1: Option[Int] = Some(7)
可能值得问一下为什么你丢失了静态类型信息,你需要模式匹配。