繁体   English   中英

折叠选项与折叠收集

[英]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()集合不是空的,我怎么能优雅地返回它?

请注意,您的实例OptionSeq是不等效的:在前一种情况下,其结果是,这是内部Option或空字符串,而在后一种情况下,你最终返回集合本身 ,而不是它内容。

你可以做的你做了什么有相当的Optionfold的藏品太多,这取决于你想如何处理集合中的多个值。 例如:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM