在Scala中,表达一下:
val opt:Option[String] = Some("a")
if(opt.isEmpty) "" else opt.get
您可以在fold
上使用此Options
模式:
opt.fold("")(_)
但集合上的fold
行为有所不同。如何在不必编写的情况下为集合实现相同的目标:
case class Container(description: String, collection: Seq)
val col = Seq()
if(col.nonEmpty) {
Some(Container("some description", col))
} else {
None
}
换句话说,我怎样才能优雅地返回Some()
集合,只有当它不为空时?
答案 0 :(得分:2)
请注意,Seq
和Option
的示例不相同:在前一种情况下,结果是里面的值 {{1}或者是一个空字符串,而在后一种情况下,你最终会返回集合本身,而不是它的内容。
您可以使用Option
对集合执行相同的操作,具体取决于您希望如何处理集合中的多个值。例如:
fold
会将集合中的所有字符串连接成一个长字符串(您可以使用seqOfStrings.foldLeft("") { _ + _ }
得到相同的结果)。请注意,这使用seqOfStrings.mkString
而不是foldLeft
,因为前者(应该是)可并行化,并且不保证按顺序处理结果。以下是fold
的示例:
fold
这当然与 seqOfInts.fold(0) { _ + _ }
seqOfInts.sum
(左/右)的想法是将集合的所有元素组合(“折叠”)为单个值。 fold
是一个特殊情况,因为它只能包含一个元素,因此变换器函数不需要带两个参数,看起来很像Option
的相反 - 因此你的混乱。
您要对集合进行的操作实际上并不是折叠的用例。您可以使用getOrElse
作为其他答案建议,或者更好的是模式匹配:
headOption
你可以将它包装到伴侣对象中,看起来更漂亮:
col match {
case Seq() => None
case x => Some(Container("some description", x))
}
现在,你可以在别处做 object Container {
def apply[T](seq: Seq[T]) = seq match {
case Seq() => None
case s => Container("some description", x))
}
}
。
答案 1 :(得分:1)
您对fold
的期望是错误的,不是关于Option
关于使用收集的问题,它与Option
一起使用,因为它们也是收藏品。
使用fold
,您将为第一个参数提供一个起始值,并提供一个将应用于集合的函数。
关于您的问题:
您分享的代码看起来不错,但如果您真的想要映射某些选项,您可以使用headOption
并将其映射到您想要的值,但这不会使您的代码更优雅或明确
答案 2 :(得分:0)
这有点短,虽然也不是很优雅:
forloop
或者,但IMO甚至更丑(我刚看到Hüseyin也提到了它):
Option(col.nonEmpty).collect { case true => Container("some description", col) }