折叠选项 vs 折叠 Collection

Fold on Option vs Fold on Collection

在 Scala 中,要表达这个:

val opt:Option[String] = Some("a")
if(opt.isEmpty) "" else opt.get

您可以在 Options 上使用此 fold 模式:

opt.fold("")(_)

但是 collection 上的 fold 表现不同。我怎样才能为 collections 实现同样的效果,而不必写:

case class Container(description: String, collection: Seq)
val col = Seq()
if(col.nonEmpty) {
    Some(Container("some description", col))
} else {
    None
}

也就是说,我怎么才能优雅 return Some() collection 只有不空的时候才可以

这个有点短,虽然也不是很优雅:

Option(col.nonEmpty).collect { case true => Container("some description", col) }

或者,但 IMO 更丑陋(我刚刚看到 Hüseyin 也建议了):

col.headOption.map(Container("some description", col))

您对 fold 的期望是错误的,这与 Option 无关,而是与集合有关,并且与 Option 一起工作,因为它们也是集合。

使用 fold 时,您将使用第一个参数提供起始值并提供将应用于集合的函数。

关于你的问题: 您共享的代码看起来不错,但是如果您 真的 想要映射某些选项,您可以使用 headOption 并将其映射到您想要的值,但这不会使您的代码更优雅或清除

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

您也可以对集合使用 fold 执行与 Option 相同的操作,具体取决于您希望如何处理集合中的多个值。例如:

seqOfStrings.foldLeft("") { _ + _ }

会将集合中的所有字符串连接成一个长字符串(使用 seqOfStrings.mkString 可以获得相同的结果)。请注意,这使用 foldLeft 而不是 fold,因为前者(应该)是可并行的,并且不能保证按顺序处理结果。这是 fold:

的示例
 seqOfInts.fold(0) { _ + _ }

这当然和seqOfInts.sum

一样

fold (left/right) 的想法是将集合的所有元素组合 ("folding") 为一个值。 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)