簡體   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