[英]Fold on Option vs Fold on Collection
在Scala中,要表达这一点:
val opt:Option[String] = Some("a")
if(opt.isEmpty) "" else opt.get
您可以在Options
上使用此fold
模式:
opt.fold("")(_)
但是,集合上的fold
表现不同。 如何在集合中实现相同的功能,而无需编写:
case class Container(description: String, collection: Seq)
val col = Seq()
if(col.nonEmpty) {
Some(Container("some description", col))
} else {
None
}
换句话说,如果Some()
集合不是空的,我怎么能优雅地返回它?
请注意,您的实例Option
和Seq
是不等效的:在前一种情况下,其结果是,这是内部值Option
或空字符串,而在后一种情况下,你最终返回集合本身 ,而不是它内容。
你可以做的你做了什么有相当的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))
}
}
现在,您可以在其他地方执行Container(seq)
。
您对fold
期望是错误的,它不是关于Option
,而是关于使用集合,它与Option
因为它们也是集合。
使用fold
您可以使用第一个参数提供起始值,并提供将应用于集合的函数。
关于你的问题:你共享的代码看起来很好,但如果你真的想要映射一些选项,你可以使用headOption
并将其映射到你想要的值,但这不会使你的代码更优雅或清晰
这有点短,虽然也不是很优雅:
Option(col.nonEmpty).collect { case true => Container("some description", col) }
或者,但IMO甚至更丑(我刚看到Hüseyin也提到了它):
col.headOption.map(Container("some description", col))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.