[英]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.