Reputation: 1819
Two objects extend a base object like this:
trait Component
class ComponentA extends Component
class ComponentB extends Component
Let's say I have some objects instantiated:
val a = new ComponentA
val a2 = new ComponentA
val b = new ComponentB
I'm given a list of type Component
, like this:
val components = List[Components](a, a2, b)
What I want to do is have a function that takes a list of mixed type and transforms it into an n-tuple of lists containing only one type. So for example, components
would break down like this:
transform.apply(components) = (List(a, a2), List(b))
The nonfunctional, grotesque, Frankensteinian way to do this is:
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
}
Obviously there's tons of drawbacks to this method:
ListBuffer
, doesn't leverage the Collections
library.)Is there a way I can get this accomplished with FP in Scala? My initial thought was to use some sort of groupBy
function with an internal case/match for type inspection?
Upvotes: 0
Views: 95
Reputation: 22439
Consider using foldRight
to traverse the components
list to assemble the (List[ComponentA], List[ComponentB])
tuple:
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))
Upvotes: 1
Reputation: 8584
I would use collect:
val aList = c.collect { case a: ComponentA => a }
val bList = c.collect { case b: ComponentB => b }
val res = (aList, bList)
Upvotes: 1
Reputation: 1293
Well, why not just use the groupBy
with your class like:
c.groupBy(_.getClass).values
This will already give you a List
of Lists
with the grouped instances in it. Getting a tuple is more complicated as you need to know the type beforehand. There is solutions using Shapeless (Convert a Scala list to a tuple?) but not sure you really have to go that far as your original solution seems to work without an actual tuple.
Upvotes: 3