Вопрос

Lets say I have a List[TraitA] of objects. TraitA provides a property propX : String. I know that a subset of this list is also an instance of TraitB, which however does not provide the property propX.

So for example:

trait TraitA
{
  def propX : String
}

trait TraitB
{
  def abc : Int
}

Some of the instances in the list just extend TraitA, while others extend TraitA with TraitB. I need to extract only those instances which have TraitB but I need to retain the property propX from TraitA. propX can only be a few values, and what I need is a Map which groups the instances of TraitB according to this value.

So what I need to extract is this subset of TraitB instances from the List[TraitA] instances, since some of them are TraitA with TraitB, and create a Map[String, List[TraitB]], where the key is propX from TraitA.

I have been fiddling around with for comprehensions but for some reason I can't yield a List[(String, TraitB)] of tuples (which I could then groupBy _.1), probably because the first generator is of type TraitA.

I tried this, but it complains that the expected type is List[(String, TraitA)]:

for {
traitA <- listOfTraitAs
traitBoption = (traitA match {
    case traitB : TraitB => Some(traitB)
    case _ => None
   })
} yield (traitA.propX, traitBoption)

On the other hand, if I filter the list by pattern matching on TraitB I lose visibility of propX in the filtering function.

What is the best approach to achieve this?

Это было полезно?

Решение

I don't see why filter does not work for you:

scala> trait TraitA { def propX: String }; trait TraitB { def abc: Int }
defined trait TraitA
defined trait TraitB

scala> class A extends TraitA { def propX = util.Random.nextInt(5).toString() }
defined class A

scala> class B extends A with TraitB { def abc = util.Random.nextInt(5) }
defined class B

scala> val xs: List[TraitA] = List.fill(15)(if (util.Random.nextBoolean()) new A else new B)
xs: List[TraitA] = List(A@6b46e91a, B@7c71e0fb, A@1869be91, B@465e2e1c, B@5125545b, A@69c54bfb, B@17ff81fd, A@7af155a, B@77a2cba6, A@60e83ca6, A@2ee5e7fe, B@77e1ecbf, A@117e2d16, A@72c20852, B@20b07a5a)

scala> xs collect { case a: TraitB => a } groupBy (_.propX)
res7: scala.collection.immutable.Map[String,List[TraitA with TraitB]] = Map(4 -> List(B@465e2e1c, B@77e1ecbf), 1 -> List(B@77a2cba6), 0 -> List(B@20b07a5a), 2 -> List(B@7c71e0fb, B@17ff81fd), 3 -> List(B@5125545b))

Even if you loose visibility, you can always do a pattern match with something like { case a: TraitA with TraitB => }.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top