更简洁的方式类匹配和访问最后一个选项[列表]
我有一个函数,作为参数需要一个对象,如果它是正确的类型,我需要访问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仍然很陌生,想要学习更好的解决这类问题的方法。
你的情况,最初似乎有什么恩德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
}
但是如果你仔细研究它,你会发现你的代码中有一个bug,如果是那个obj.listOfInts is Some(Nil)
,因为在这种情况下,你会得到一个NoSuchElementException,试图在空List上调用Last。
试试这个代码与foo = Bar(Some(Nil))
并亲自看看。
当您使用选项[列表]认真思考如果这是你想要的。 通常在经过一番思考之后,您会放弃该选项,只留一个列表,因为该选项没有用处。 我曾与很多开发者滥用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
}
}
正如你所看到的无壳和一些(无)情况基本相同。
要解决你的错误,你应该做的:
case class Bar(listOfInts: Option[List[Int]])
val i = foo match {
case Bar(Some(list)) if list != Nil => list.last
case _ => 0
}
正如意见建议,我认为最好的方法是:
val i = foo match {
case obj: Bar => obj.listOfInts.map(_.last).getOrElse(0)
case _ => 0
}
你可能想使用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([email protected](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
}
's /可能/绝对'。 –
更简洁的方式包括的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)
可能值得问一下为什么你丢失了静态类型信息,你需要模式匹配。
它可能是应该被设计得更好一些的东西,但是我们有一些超类的几个不同的子类型,它们有一些在这个函数中有特殊的属性。 – Rig
您可以避免与'obj.listOfInts.map(_。last).getOrElse(0)'的第二次匹配。 –
感觉解决方案笨拙并需要改进是一个很好的信号,表明您正在学习某些东西。这可能是更多的代码审查问题,虽然.. – beefyhalo
@beefyhalo你其实可能是正确的,我不会介意它被迁移到那里。我其实已经忘记了甚至存在。 – Rig