说,我有以下对象:
case class MyFancyObject(a: String, b: Int, c : Vector[String])
我需要的是获得一个Vector[String]
个包含与给定部分功能相匹配的所有内容的val xs = Vector(
MyFancyObject("test1",1,Vector("test1-1","test1-2","test1-3")),
MyFancyObject("test2",2,Vector("test2-1","test2-2","test2-3")),
MyFancyObject("test3",3,Vector("test3-1","test3-2","test3-3")),
MyFancyObject("test4",4,Vector("test4-1","test4-2","test4-3"))
)
val partialFunction1 : PartialFunction[MyFancyObject,Vector[String]] = {
case MyFancyObject(_,b,c) if b > 2 => c
}
。
例如:
Vector("test3-1","test3-2","test3-3","test4-1","test4-2","test4-3")
我需要得到的是:val res1 = xs.foldMap{
case MyFancyObject(_,b,c) if b > 2 => c
case _ => Vector.empty[String]
}
。
我解决了这个问题:
Monoid
然而,这让我很好奇。我在这里做的似乎是一个非常普遍和自然的事情:对于可折叠集合的每个元素,尝试应用部分函数,如果失败,则默认为empty
' s {{ 1}}(在我的情况下为Vector.empty
)。我在图书馆搜索了,我没有发现任何事情,所以我最终在我的代码中添加了这个扩展方法:
implicit class FoldableExt[F[_], A](foldable : F[A]) {
def foldCollect[B](pF: PartialFunction[A, B])(implicit F : Foldable[F], B : Monoid[B]) : B = {
F.foldMap(foldable)(pF.applyOrElse(_, (_ : A) => B.empty))
}
}
我的问题是:
有没有理由为什么这种方法不可用?这不是一个通用和常见的场景,还是我错过了什么?
答案 0 :(得分:2)
我认为如果你真的需要部分功能,你不希望它泄漏到外面,因为它不是很好用。如果您想重复使用partialFunction1
,最好的办法是lift
使其成为返回Option
的总函数。然后,您可以在使用部分功能的同一位置提供默认情况。这是方法:
val res2 = xs.foldMap(partialFunction1.lift).getOrElse(Vector.empty)
foldMap(partialFunction1.lift)
返回Some(Vector(test3-1, test3-2, test3-3, test4-1, test4-2, test4-3))
。这正是res1
中的内容,但包含在Option
中。