两个对象扩展了这样的基础对象:
trait Component
class ComponentA extends Component
class ComponentB extends Component
假设我有一些实例化的对象:
val a = new ComponentA
val a2 = new ComponentA
val b = new ComponentB
我得到了Component
类型的列表,像这样:
val components = List[Components](a, a2, b)
我想要做的是有一个函数,该函数接收混合类型的列表,并将其转换为仅包含一种类型的列表的n个元组。例如,components
会像这样分解:
transform.apply(components) = (List(a, a2), List(b))
执行此操作的非功能性,怪诞的,科学怪人的方式是:
def apply(c: List[Component]) = {
var aComponents = new ListBuffer[ComponentA]()
var bComponents = new ListBuffer[ComponentB]()
for (c <- components) {
c match {
case aType: ComponentA => aComponents += aType
case bType: ComponentB => bComponents += bType
case _ => None
}
}
aComponents -> bComponents
}
这种方法显然有很多缺点:
ListBuffer
,不使用Collections
库。)有没有办法让我在Scala中使用FP完成此任务?我最初的想法是使用带有内部大小写/匹配项的groupBy
函数进行类型检查?
答案 0 :(得分:3)
好吧,为什么不将groupBy
与类似的类一起使用:
c.groupBy(_.getClass).values
这将为您提供List
中的Lists
,其中包含已分组的实例。获取元组更为复杂,因为您需要事先了解类型。有一些使用Shapeless(Convert a Scala list to a tuple?)的解决方案,但是不确定原始的解决方案似乎在没有实际元组的情况下确实可以工作。
答案 1 :(得分:1)
考虑使用foldRight
遍历components
列表以组装(List[ComponentA], List[ComponentB])
元组:
components.foldRight( (List[ComponentA](), List[ComponentB]()) )(
(x, acc) => x match {
case x: ComponentA => (x :: acc._1, acc._2)
case x: ComponentB => (acc._1, x :: acc._2)
case _ => acc
}
)
// res1: (List[ComponentA], List[ComponentB]) =
// (List(ComponentA@24a298a6, ComponentA@74fe5966), List(ComponentB@2bfbffb2))
答案 2 :(得分:1)
我将使用collect:
val aList = c.collect { case a: ComponentA => a }
val bList = c.collect { case b: ComponentB => b }
val res = (aList, bList)