折叠选项与折叠收集

时间:2016-07-08 08:49:32

标签: scala collections scala-collections

在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()集合,只有当它不为空时?

3 个答案:

答案 0 :(得分:2)

请注意,SeqOption的示例不相同:在前一种情况下,结果是里面的值 {{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) }