假设我有List[TraitA]
个对象。 TraitA
提供了一个属性propX : String
。
我知道此列表的一个子集也是TraitB
的一个实例,但是它不提供属性propX
。
例如:
trait TraitA
{
def propX : String
}
trait TraitB
{
def abc : Int
}
列表中的部分实例只有extend TraitA
,而有些extend TraitA with TraitB
。我只需要提取那些TraitB
的实例,但我需要保留propX
中的属性TraitA
。 propX
只能是一些值,而我需要的是Map
,它根据此值对TraitB
的实例进行分组。
所以我需要提取的是来自TraitB
个实例的List[TraitA]
个实例的子集,因为其中一些实例是TraitA with TraitB
,并创建了一个Map[String, List[TraitB]]
,其中密钥是来自propX
的{{1}}。
我一直在摆弄TraitA
理解但由于某种原因,我不能for
yield
元组(我可以List[(String, TraitB)]
),可能是因为第一个生成器是groupBy _.1
类型。
我试过这个,但它抱怨预期的类型是TraitA
:
List[(String, TraitA)]
另一方面,如果我for {
traitA <- listOfTraitAs
traitBoption = (traitA match {
case traitB : TraitB => Some(traitB)
case _ => None
})
} yield (traitA.propX, traitBoption)
按filter
上的模式匹配列表,我会在过滤功能中失去TraitB
的可见性。
实现这一目标的最佳方法是什么?
答案 0 :(得分:2)
我不明白为什么filter
不适合你:
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))
即使您失去了可见性,也可以使用{ case a: TraitA with TraitB => }
等方式进行模式匹配。