class 匹配和访问 Option[List] 的最后一个的更简洁的方法
More concise way to class match and access last of Option[List]
我有一个函数,它接受一个对象作为参数,如果它是正确的类型,我需要访问 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
}
从技术上讲,它可以 return 和 Option[Int]
。我对 Scala 还是很陌生,想学习更好的方法来解决这类问题。
根据评论中的建议,我认为最好的方法是:
val i = foo match {
case obj: Bar => obj.listOfInts.map(_.last).getOrElse(0)
case _ => 0
}
在您的情况下,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 试图最后调用一个空列表。
用 foo = Bar(Some(Nil))
试试这个代码,然后自己看看。
当您使用 Option[List] 时,请仔细考虑这是否是您想要的。
通常经过一番思考后,您会放弃该选项并继续使用列表,因为该选项没有任何用处。
我与许多滥用 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
}
}
如您所见,None 情况和 Some(Nil) 情况基本相同。
要修复您的错误,您应该这样做:
case class Bar(listOfInts: Option[List[Int]])
val i = foo match {
case Bar(Some(list)) if list != Nil => list.last
case _ => 0
}
你可能想在这里使用 flatMap
和 lastOption
:
obj.listOfInts.flatMap(_.lastOption)
如果 listOfInts
是 None
,或者是 Some(Nil)
,这将 return None
。否则它将 return 最后一个元素。如果您想 return 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
}
包括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)
可能值得一问为什么你丢失了静态类型信息,你需要模式匹配。
我有一个函数,它接受一个对象作为参数,如果它是正确的类型,我需要访问 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
}
从技术上讲,它可以 return 和 Option[Int]
。我对 Scala 还是很陌生,想学习更好的方法来解决这类问题。
根据评论中的建议,我认为最好的方法是:
val i = foo match {
case obj: Bar => obj.listOfInts.map(_.last).getOrElse(0)
case _ => 0
}
在您的情况下,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 试图最后调用一个空列表。
用 foo = Bar(Some(Nil))
试试这个代码,然后自己看看。
当您使用 Option[List] 时,请仔细考虑这是否是您想要的。 通常经过一番思考后,您会放弃该选项并继续使用列表,因为该选项没有任何用处。 我与许多滥用 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
}
}
如您所见,None 情况和 Some(Nil) 情况基本相同。
要修复您的错误,您应该这样做:
case class Bar(listOfInts: Option[List[Int]])
val i = foo match {
case Bar(Some(list)) if list != Nil => list.last
case _ => 0
}
你可能想在这里使用 flatMap
和 lastOption
:
obj.listOfInts.flatMap(_.lastOption)
如果 listOfInts
是 None
,或者是 Some(Nil)
,这将 return None
。否则它将 return 最后一个元素。如果您想 return 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
}
包括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)
可能值得一问为什么你丢失了静态类型信息,你需要模式匹配。